Shop OBEX P1 Docs P2 Docs Learn Events
Catalina 3.0 - Page 5 — Parallax Forums

Catalina 3.0

1235717

Comments

  • Heater.Heater. Posts: 21,230
    edited 2011-04-20 22:45
    Nothing, Catalina is a not a native Prop program. It is a cross compiler.

    I guess one could compile Catalina with Catalina on a PC resulting in a Catalina that will run on the Prop.
    Provided the Prop has a big enough external RAM and file store to run it.
    I also guess bootstrapping a native Catalina like that is not so easy. I believe RossH already this idea in mind.
  • RossHRossH Posts: 5,519
    edited 2011-04-20 23:07
    Heater. wrote: »
    Nothing, Catalina is a not a native Prop program. It is a cross compiler.

    I guess one could compile Catalina with Catalina on a PC resulting in a Catalina that will run on the Prop.
    Provided the Prop has a big enough external RAM and file store to run it.
    I also guess bootstrapping a native Catalina like that is not so easy. I believe RossH already this idea in mind.

    Yes, very early on I compiled Catalina with Catalina and produced a compiler that would run on the Prop. The trouble is that there was no point in going any further - for three reasons:

    1. Insufficient RAM on any Prop plaform. I can't recall how big the result was, but it was certainly too large for any platform I had at the time. Maybe now that we have boards with 32Mb RAM we might be able to run it.

    2. Catalina requires a PASM assembler, and (again, at the time) there was no assembler that could run on the Propeller. Maybe now that we have Sphinx this might be possible.

    3. Although everybody says they would like to see this, nobody actually has any practical use for it!

    Ross.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-21 07:29
    RossH wrote:
    heater wrote:
    Nothing, Catalina is a not a native Prop program. It is a cross compiler.

    I guess one could compile Catalina with Catalina on a PC resulting in a Catalina that will run on the Prop.
    Provided the Prop has a big enough external RAM and file store to run it.
    I also guess bootstrapping a native Catalina like that is not so easy. I believe RossH already this idea in mind.
    Yes, very early on I compiled Catalina with Catalina and produced a compiler that would run on the Prop. The trouble is that there was no point in going any further - for three reasons:
    Though yet in response to my earlier statement about Catalina not being very useful because it is not Prop native you said:
    RossH wrote:
    Hi David,

    You should read the Catalina documentation. Catalina runs "out of the box" on any Propeller, including all the boards you mentioned!

    So 32k is insufficient, even though many ANSI C compilers have been made that can run in 12K or less with out overlays and without accessing external storage. You definitely have me wondering about how a C compiler could so big (even with the LMM stuff), I guess I am going to be looking at the source very closely.

    And as for a Practical use; How about developing a true Propeller computer, or not being tied to Linux or Windoze to use it with out a lot of work in porting it? It is not fully ANSI C from the little bit of code that I have already browsed, and GCC is not as universal as they would like to be.
  • David BetzDavid Betz Posts: 14,516
    edited 2011-04-21 07:37
    So 32k is insufficient, even though many ANSI C compilers have been made that can run in 12K or less with out overlays and without accessing external storage. You definitely have me wondering about how a C compiler could so big (even with the LMM stuff), I guess I am going to be looking at the source very closely.
    Could you please point me to even a single ANSI C compiler that can run in 12k or less without overlays? You seem to be talking about the compiler itself running in that amount of memory not the code that it generates. Catalina can certainly generate code that will run in 12k of memory without overlays. It's just that the compiler itself can't run in that little space. I seriously doubt that even with hand crafted assembly language you'd be able to get a full ANSI C compiler to fit in 12k. However, I'd love to be proved wrong! :-)
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-21 08:11
    David Betz:
    I will try to track down one or more of these old compilers for you (I no longer have a 5.25 inch floppy drive). Many of them did not include support for wide string libs, also many of them relied on the program not having to many dependencies on static Libs, though they still fit in 12k (plus 4KB to 8KB for the source file plus 2KB to 8KB for the generated binary), and were 100% ANSI compliant. They did this by using a single pass compiler that directly generated binary executable object or linkable object code, if they needed to do any linking other than the standard lib this did require access to mass storage (of course), and they did not support inline assembly (which is not part of the standard anyway).
  • David BetzDavid Betz Posts: 14,516
    edited 2011-04-21 08:16
    David Betz:
    I will try to track down one or more of these old compilers for you (I no longer have a 5.25 inch floppy drive). Many of them did not include support for wide string libs, also many of them relied on the program not having to many dependencies on static Libs, though they still fit in 12k (plus 4KB to 8KB for the source file plus 2KB to 8KB for the generated binary), and were 100% ANSI compliant. They did this by using a single pass compiler that directly generated binary executable object or linkable object code, if they needed to do any linking other than the standard lib this did require access to mass storage (of course), and they did not support inline assembly (which is not part of the standard anyway).

    Thanks! I'll be looking forward to seeing one of these. I know there were small C compilers back in the early micro days. Certainly there was Small C but I don't think it fit in 14k. It is more likely that BDS C would fit in that much memory but I think it was multi-pass and was written in assembly language and it was not an ANSI C compiler since the ANSI standard didn't exist back then. I'm sure there are many others that I am not familiar with.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-21 08:32
    David Betz:
    http://floppysoftware.vacau.com/c_compilers.html
    I think this page may interest you, it does not fully answer the question (though many of these came close to ANSI C before the standard existed). I wish I could remember the names of some of those early ANSI C compilers, they were truly works of eloquence (in the mathematical since of eloquence), very small and efficient.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-21 08:57
    For one efficient way to create a single pass compiler I recommend the tutorial at:
    http://compilers.iecc.com/crenshaw/
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-21 16:38
    Catalina runs "out of the box" on any Propeller, including all the boards you mentioned!

    I think the misunderstanding here is that instead of "Catalina runs on any propeller' it should perhaps be reworded "Programs compiled with Catalina run on any propeller".

    However, having said that, it is possible to compile C programs on a propeller that have been written totally on the propeller. This has been done within the CP/M emulation, with the program written in Wordstar and compiled using BDSC. It does work, but it is slow (several minutes to compile "Hello World"). Having used this, I think that the hard part may not be the compiler, but rather the text editor.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-21 18:55
    Dr_Acula:
    Thank you. I supose that a good text editor would be difficult to implement in this space, though a simple screen editor based text file editor should do, or maybe a COPY CON, ECHO >, or EDLIN style editor :) . Has any one attempted a full blown text editor on the prop yet??? It would not have to run at the same time as the compiler, which in turn would not have to run at the same time as the linker.
  • RossHRossH Posts: 5,519
    edited 2011-04-21 19:08
    So 32k is insufficient, even though many ANSI C compilers have been made that can run in 12K or less with out overlays and without accessing external storage. You definitely have me wondering about how a C compiler could so big (even with the LMM stuff), I guess I am going to be looking at the source very closely.

    Hi David,

    Sorry if I misled you. As Dr_A points out, I should have said "Catalina can compile programs that can run on any Propeller" - my mistake!

    However, I don't think you will find an ANSI C compiler that can run in 12k. You may be thinking of the original Tiny C - this program had a code size under 12k (on x86), but it implemented only a small fraction of the original C language (which is in turn smaller than the current ANSI C).

    In any case, even if a C compiler had a code size of 12k (and for various reasons I will go into later, the code size would be much larger than that on the Prop), you still need more space than that to actually compile anything - e.g. to store the symbol table. Exactly how much space you need depends on the program being compiled, but you aren't going to be able to compile much in the way of non-trivial programs in only 32kb of non-virtual, non-overlaid memory.

    I believe ANSI C compilers would take more like hundreds of kb of code size, plus whatever data size is required for the program being compiled. The smallest C compiler I know of is probably the current version of the original Tiny C compiler (http://bellard.org/tcc/) - this claims to be ANSI compliant, but weighs in with a code size of around 100kb (on x86). But again you need more memory than that to actually compile anything - although perhaps not much more since it claims to be single-pass.

    Another thing to remember is that these compilers all run under an operating system - i.e. they do not need to carry around their own file system and SD card drivers just to be able to read the C source! A propeller compiler has to do all that and more. Out of interest, I just used Catalina to compile the original version of the Tiny C compiler (remember it has a code size of 12k on x86) and its size on the Propeller (including all the file system and I/O drivers necessary to run it) ends up with a code size of 66k! And this for a compiler that implements only a fraction of ANSI C. I didn't try compiling the current version of Tiny C, but my guess would be it would end up with a code size of at least 300k on the Propeller.

    And it gets worse, of course - very few modern compilers are single pass, because such compilers offer little or no opportunity for code optimization. I don't know what the code produced by Tiny C is like, but it is probably terribly inefficient. Most C compilers are multi-pass to allow for useful things like register optimization, common sub-expression re-use and dead code elimination. Even LCC has fairly sophisticated capabilities in this area. But with a multi-pass compiler you also need to store the intermediate parse trees - and this needs quite a lot of additional memory space for a non-trivial program.

    From memory, I think I figured out that LCC would require something like 3 to 4Mb to compile itself from C down to PASM on the Propeller - and even if it could, there is currently no assembler that can run on the Prop capable of assembling that PASM into a final binary.

    Ross.
  • RossHRossH Posts: 5,519
    edited 2011-04-21 19:10
    Dr_Acula:
    Thank you. I supose that a good text editor would be difficult to implement in this space, though a simple screen editor based text file editor should do, or maybe a COPY CON, ECHO >, or EDLIN style editor :) . Has any one attempted a full blown text editor on the prop yet??? It would not have to run at the same time as the compiler, which in turn would not have to run at the same time as the linker.

    Hi David,

    Catalyst (Catalina's SD card loader) comes with a version of the vi text editor.

    Ross.
  • RossHRossH Posts: 5,519
    edited 2011-04-21 19:28
    And as for a Practical use; How about developing a true Propeller computer, or not being tied to Linux or Windoze to use it with out a lot of work in porting it? It is not fully ANSI C from the little bit of code that I have already browsed, and GCC is not as universal as they would like to be.

    I'm not sure what you mean here. Do you mean a Propeller-based operating system? There are several groups working on one - search these forums and you'll find several ongoing projects (plus lots of idle speculations about porting linux etc).

    As to being "not fully ANSI C" - what are you referring to? LCC itself is certainly ANSI C, and so is the Catalina back-end code generator. So are the Catalina libraries. But of course the Propeller run-time support package is not, since that would presume the existence of an ANSI compliant C compiler and associated run-time support package (chicken, meet egg!).

    Ross.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-22 05:35
    RossH:
    By saying 'it is not fully ANSI C' I am referring to the source of Catalina that I have looked at, some of the extensions seem to be gcc style extensions. And my point in saying this is that Catalina can not be ported to every possible platform that has a C compiler with out first porting a different C compiler.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-22 05:40
    RossH:
    If Catalina will run well in not to much XMM, I think even that could be useful, assuming that the XMM driver can be easily modified by the user to use a variety of different memories, as not every one is going to have the same preferences, and many are likely to be adding there own memory to a board that comes with none.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-04-22 07:35
    Sorry I ignored this thread for a week - had a family trip to Melbourne and it was a "no internet" holiday!

    Back coding now. I thought I would tackle the graphical mouse next, mainly so I could answer the question as to whether Catalina is fast enough to draw and refresh a 273 pixel mouse pointer in real time. And the good news is that it can!

    At the moment I'm redrawing the mouse pointer from external ram but it probably would be faster again if the array was in hub ram.

    This code is not fully debugged - the bounds checking is not working so the mouse goes a bit haywire at the edges of the screen.

    It also demonstrates loading in another cogject (this program is now using 3 cogjects). I'm not sure if there is a "right" or "wrong" method in terms of plugins vs cogjects and I guess I would like to see both methods available for use. What is nice though is to be able to use the same cogject for a spin program and a C program.

    I have found that the sd card driver in Catalina is a little slow compared with Kye's SD driver. For the moment, the optimum speed solution is to load all cogjects into XMM at bootup, as it is faster to load a cogject from XMM into a cog than it is to load from SD into cog. That could change down the track.

    At the moment it boots up, displays some text messages on the Catalina VGA text driver, then shuts down cogs 1 and 3, reuses cog 1 for two other VGA displays and puts the mouse in cog 7. This leaves cog 3 free.

    I am starting to see some real advantages to coding in a way that reuses cogs over and over. Want to do some floating point math and no cogs left? Simply overwrite the mouse cog with the floating point code, do the sums, then reload the mouse.

    Next step is to click on a button and redraw the button as a "clicked" button. Then it is time to tackle text boxes, which end up being de-facto word processors.
    /* PASM cogject demonstration, see also cogject example in spin*/
    
    #include <stdio.h>
    #include <string.h>
    // cogjects - sd card driver in catalina is a little slow so load up once into external ram then (re) load quicker from external ram      
    	unsigned long cogject_color[512];					// external memory for color vga driver
    	unsigned long cogject_gray[512];					// external memory for gray vga driver
    	unsigned long cogject_mouse[512];					// external memory for mouse driver
    
    	unsigned long mouse_mask[21] = {							// mask 00=pixel, 11=transparant
    	0xfffffff0,0xffffffc0,0xffffff00,0xfffffc00,0xfffff000,0xffffc000,	// order is reversed in each long
    	0xffff0000,0xfffc0000,0xfff00000,0xffc00000,0xff000000,0xfc000000,
    	0xfffc0000,0xfffc0000,0xfff00300,0xfff003c0,0xffc00ff0,0xffc00fff,
    	0xff003fff,0xff003fff,0xffc0ffff
    	};
    	unsigned long mouse_icon[21] = {							// icon, 00, 01, 10 or 11=pixel, 00 = transparent if transparent above
    	0x00000004,0x00000010,0x0000004c,0x0000013c,0x000004fc,0x000013fc,
    	0x00004ffc,0x00013ffc,0x0004fffc,0x0013fffc,0x004ffffc,0x01003ffc,
    	0x00013cfc,0x00013c3c,0x0004f04c,0x0004f010,0x0013c004,0x0013c000,
    	0x004f0000,0x004f0000,0x00100000
    	};
    
    	unsigned long screen_external[4800]	;			// external memory for a screen buffer
    // 128 rows, one for each ascii character 0 to 127
    // first long is 0000HHWW where HH is the height in hex and WW is the width in hex
           unsigned long sans_serif_font[1664] =
           {
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c00,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000009, 0x00000009, 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000012, 0x00000012, 0x0000003f, 0x00000012, 0x00000012, 0x00000012, 0x0000003f, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000004, 0x0000000e, 0x00000015, 0x00000014, 0x0000000c, 0x00000006, 0x00000005, 0x00000015, 0x0000000e, 0x00000004, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000030, 0x00000049, 0x00000032, 0x00000004, 0x00000008, 0x00000010, 0x00000026, 0x00000049, 0x00000006, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000008, 0x00000014, 0x00000014, 0x00000008, 0x00000008, 0x00000015, 0x00000012, 0x00000012, 0x0000000d, 0x00000000, 0x00000000, 
                  0x00000c02,0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000001, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000001, 
                  0x00000c03,0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 
                  0x00000c04,0x00000000, 0x00000005, 0x00000002, 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x0000001f, 0x00000004, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000004, 0x00000004, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000004, 0x0000001c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000001, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x0000001f, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000001, 0x00000001, 0x00000006, 0x00000001, 0x00000001, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000002, 0x00000006, 0x00000006, 0x0000000a, 0x0000000a, 0x00000012, 0x0000001f, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000001f, 0x00000010, 0x00000010, 0x0000001e, 0x00000011, 0x00000001, 0x00000001, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000010, 0x00000010, 0x0000001e, 0x00000011, 0x00000011, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000001f, 0x00000001, 0x00000002, 0x00000002, 0x00000004, 0x00000004, 0x00000008, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000011, 0x00000011, 0x0000000e, 0x00000011, 0x00000011, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000011, 0x00000011, 0x0000000f, 0x00000001, 0x00000001, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000001f, 0x00000000, 0x0000001f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000000e, 0x00000011, 0x00000001, 0x00000001, 0x00000002, 0x00000004, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 
                  0x00000c0b,0x00000000, 0x00000078, 0x00000186, 0x00000102, 0x00000239, 0x00000249, 0x00000249, 0x00000237, 0x00000100, 0x00000180, 0x0000007c, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000008, 0x00000008, 0x00000014, 0x00000014, 0x00000022, 0x00000022, 0x0000003e, 0x00000041, 0x00000041, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000003c, 0x00000022, 0x00000022, 0x00000022, 0x0000003c, 0x00000022, 0x00000022, 0x00000022, 0x0000003c, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000001e, 0x00000021, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000021, 0x0000001e, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000078, 0x00000044, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000044, 0x00000078, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000003e, 0x00000020, 0x00000020, 0x00000020, 0x0000003c, 0x00000020, 0x00000020, 0x00000020, 0x0000003e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x0000001f, 0x00000010, 0x00000010, 0x00000010, 0x0000001e, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x0000003c, 0x00000042, 0x00000040, 0x00000040, 0x0000004e, 0x00000042, 0x00000042, 0x00000046, 0x0000003a, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x0000007e, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000012, 0x00000012, 0x0000000c, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000022, 0x00000024, 0x00000028, 0x00000030, 0x00000030, 0x00000028, 0x00000024, 0x00000022, 0x00000021, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x0000001f, 0x00000000, 0x00000000, 
                  0x00000c09,0x00000000, 0x00000082, 0x00000082, 0x000000c6, 0x000000c6, 0x000000aa, 0x000000aa, 0x00000092, 0x00000092, 0x00000082, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000042, 0x00000062, 0x00000062, 0x00000052, 0x00000052, 0x0000004a, 0x00000046, 0x00000046, 0x00000042, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x0000003c, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x0000003c, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000003e, 0x00000021, 0x00000021, 0x00000021, 0x0000003e, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x0000003c, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x0000004a, 0x00000046, 0x0000003c, 0x00000002, 0x00000000, 
                  0x00000c08,0x00000000, 0x0000007c, 0x00000042, 0x00000042, 0x00000042, 0x0000007c, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000001c, 0x00000022, 0x00000020, 0x00000020, 0x0000001c, 0x00000002, 0x00000002, 0x00000022, 0x0000001c, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000003e, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x0000003c, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000041, 0x00000041, 0x00000022, 0x00000022, 0x00000022, 0x00000014, 0x00000014, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 
                  0x00000c0b,0x00000000, 0x00000401, 0x00000401, 0x00000222, 0x00000222, 0x00000222, 0x00000154, 0x00000154, 0x00000088, 0x00000088, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000041, 0x00000041, 0x00000022, 0x00000014, 0x00000008, 0x00000014, 0x00000022, 0x00000041, 0x00000041, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000041, 0x00000041, 0x00000022, 0x00000014, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 
                  0x00000c07,0x00000000, 0x0000007f, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x0000007f, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000003, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000003, 
                  0x00000c05,0x00000000, 0x00000008, 0x00000008, 0x00000008, 0x00000004, 0x00000004, 0x00000002, 0x00000002, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000003, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000003, 
                  0x00000c06,0x00000004, 0x0000000a, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003f, 
                  0x00000c03,0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000001, 0x0000000f, 0x00000011, 0x00000011, 0x0000000f, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000010, 0x00000010, 0x00000010, 0x0000001e, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000001e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000011, 0x00000010, 0x00000010, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x0000000f, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000000f, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000011, 0x0000001f, 0x00000010, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000001, 0x00000002, 0x00000002, 0x00000003, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000000f, 0x00000001, 0x0000001e, 
                  0x00000c06,0x00000000, 0x00000010, 0x00000010, 0x00000010, 0x00000016, 0x00000019, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000000, 0x00000000, 
                  0x00000c02,0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 
                  0x00000c02,0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 
                  0x00000c06,0x00000000, 0x00000010, 0x00000010, 0x00000010, 0x00000012, 0x00000014, 0x00000018, 0x00000014, 0x00000012, 0x00000011, 0x00000000, 0x00000000, 
                  0x00000c02,0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000076, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000049, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000016, 0x00000019, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000e, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000000e, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000001e, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000001e, 0x00000010, 0x00000010, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x0000000f, 0x00000001, 0x00000001, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000006, 0x00000009, 0x00000004, 0x00000002, 0x00000009, 0x00000006, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000002, 0x00000002, 0x00000003, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0x00000013, 0x0000000d, 0x00000000, 0x00000000, 
                  0x00000c06,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000011, 0x00000011, 0x0000000a, 0x0000000a, 0x00000004, 0x00000004, 0x00000000, 0x00000000, 
                  0x00000c08,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000049, 0x00000049, 0x00000055, 0x00000055, 0x00000022, 0x00000022, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x00000009, 0x00000006, 0x00000006, 0x00000009, 0x00000009, 0x00000000, 0x00000000, 
                  0x00000c05,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x00000009, 0x00000009, 0x00000009, 0x00000006, 0x00000004, 0x00000004, 0x00000018, 
                  0x00000c05,0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x0000000f, 0x00000000, 0x00000000, 
                  0x00000c04,0x00000001, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000004, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000001, 0x00000000, 
                  0x00000c02,0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 
                  0x00000c04,0x00000004, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000001, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0x00000004, 0x00000000, 
                  0x00000c07,0x00000000, 0x00000000, 0x00000019, 0x00000026, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
                  0x00000c03,0x00000000, 0x00000000, 0x00000007, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0x00000007, 0x00000000, 0x00000000, 
           };
    
    // start of C functions
    
    void text_clearscreen()                                                   // white text on dark blue background
    {
           int i;
           for (i=0;i<40;i++)
           {
                   t_setpos(0,0,i);                                      // move cursor to next line
                   t_color(0,0x08FC);                                    // RRGGBBxx eg dark blue background 00001000 white text 11111100
           }
    }
    
    void sleep(int milliseconds)                                         // sleep function
    {
           _waitcnt(_cnt()+(milliseconds*(_clockfreq()/1000))-4296);
    }
    
    char peek(int address)                                               // function implementation of peek
    {
           return *((char *)address);
    }
    
    void poke(int address, char value)                                   // function implementation of poke
    {
           *((char *)address) = value;
    }
    
    // *************************************************
    //                 Runtime Functions from BCX
    // *************************************************
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    char *str (double d)
    {
      register char *strtmp = BCX_TmpStr(24);
      sprintf(strtmp,"% .15G",d);
      return strtmp;
    }
    
    char *hex (int a)
    {
     register char *strtmp = BCX_TmpStr(16);
      sprintf(strtmp,"%X",a);
      return strtmp;
    }
    // *************************************************************
    
    void external_memory_cog_load(int cognumber, unsigned long cogdata[], unsigned long parameters_array[])    	//  load a cog from external memory
    {
    	unsigned long hubcog[511];						// create a local array, this is in hub ram, not external ram	
    	int i;	
    	for(i=0;i<512;i++)								
    	{
    		hubcog[i]=cogdata[i];					// move from external memory to a local array in hub
    	}
     	_coginit((int)parameters_array>>2, (int)hubcog>>2, cognumber);		// load the cog
    }  
    
    int EoF (FILE* stream)
    {
      	register int c, status = ((c = fgetc(stream)) == EOF);
      	ungetc(c,stream);
      	return status;
    }
    
    void readcog(char *filename,unsigned long external_cog[])		// read in a .cog file into external memory array 
    {
    	int i;
    	FILE *FP1;
    	i = 0;
    	if((FP1=fopen(filename,"rb"))==0)					// open the file
       	{
      		fprintf(stderr,"Can't open file %s\n",filename);
    		exit(1);
       	}
      	fseek(FP1,0,0);
    	for(i=0;i<24;i++)
    	{
    		getc(FP1);							// read in the first 24 bytes and discard
    	}
    	i = 0;
      	while(!EoF(FP1) & (i<505))						// run until end of file or 511-6
    	{
    		external_cog[i] = getc(FP1) | (getc(FP1)<<8) | (getc(FP1)<<16) | (getc(FP1)<<24);	// get the long
    		i+=1;
    	}
    	if(FP1)
           {
         		fclose(FP1);							// close the file
         		FP1=NULL;
       	}
    	//printf("external array cog first long = 0x%x \n",external_cog[0]);	// hex value
    }
    
    void pix_clearscreen(unsigned long screen[])
    {
    	int i;
    	for (i=0;i<4800;i++)
    	{
    		screen[i] = 0x00000000;		// fill with black, use longs rather than bytes so 4 pixels per loop
    	}
    }
    
    void pix_pixel(unsigned long screen[], int x, int y, char color)
    {
    	poke((y*160+x+(unsigned long)&screen[0]),color);		
    }
    
    void pix_readscreen(char *filename, unsigned long screen[])		// read a full screen 19200 byte file into the screen
    {
    	int i;
    	FILE *FP1;
    	i = 0;
    	FP1=fopen(filename,"rb");					// open the file
      	fseek(FP1,0,0);
    	for(i=0;i<=4800;i++)
    	{
    		screen[i] = getc(FP1) | (getc(FP1)<<8) | (getc(FP1)<<16) | (getc(FP1)<<24);	// get the long
    	}
    	fclose(FP1);							// close the file
         	FP1=NULL;
    }
    
    char pix_color(char red,char green,char blue)				// pass red,green,blue 0-3, returns a combined value
    {
    	return ((red & 0x3) << 6 ) | ((green & 0x3) << 4) | ((blue & 0x3) << 2);
    }
    
    void pix_screengray(unsigned long screen[])				// whole screen gray
    {
    	int i;
    	for(i=0;i<4800;i++)
    	{
    		screen[i] = 0xa8a8a8a8;					// same as pix_color(2,2,2)
    	}
    }
    
    void pixenginestart(int cognumber, unsigned long cogarray[], unsigned long screen[], unsigned long pingroup, char color_parameters[])
    {
    	int i;
    	unsigned long frequencystate;
    	screen[2] = (0xff << (8*pingroup));
    	screen[3] = (0x300000ff | (pingroup << 9));      
    	frequencystate = ((25175000 + 1600) / 4);
    	screen[4] = 1;
    	for(i=0;i<32;i++)
    	{
    		frequencystate = frequencystate << 1;
    		screen[4] = (screen[4] << 1) | (screen[4] >> 31);
    		if (frequencystate >= _clockfreq())
    		{
    			frequencystate -= _clockfreq();
    			screen[4] += 1;
    		}
    	}
    	color_parameters[0] = 1;			// displayindicator
    	color_parameters[1] = 0;			// syncindicator
    	screen[0] = (unsigned long) &color_parameters[0]; // pointer to displayindicator
    	screen[1] = (unsigned long) &color_parameters[1]; // pointer to syncindicator
    	_cogstop(cognumber); 					// stop just before starting the next one
    	external_memory_cog_load(cognumber,cogarray,screen);		// load from external ram, pass some values in screen[]
    	//pix_clearscreen(screen);					// clear the screen to black
    	pix_screengray(screen);					// screen gray
    }
    
    void pix_colorbar(unsigned long screen[])
    {
    	int x;
    	int c;
    	x = 0;
    	for (c=0;c<64;c++)
    	{
    		pix_pixel(screen,x+10,6,(c<<2));			// print all the colors in a bar
    		x++;
    	}
    }
    
    void pix_line(unsigned long screen[], int startx, int starty, int endx, int endy, char color) 
    {
    	int row;								// also does an unfilled box
    	int col;
    	for(col=startx;col <= endx ;col++)
    	{
    		pix_pixel(screen,col,starty,color);			// horizontal lines
    		pix_pixel(screen,col,endy,color);
    	}
    	for(row=starty;row <= endy;row++)
    	{
    		pix_pixel(screen,startx,row,color);
    		pix_pixel(screen,endx,row,color);
    	}
    }
    
    void pix_box_fill(unsigned long screen[], int startx, int starty, int endx, int endy, char color) 
    {
    	int row;
    	int col;
    	for(row =starty;row <= endy; row++)
    	{
    		for(col=startx;col <=endx; col++)
    		{
    			pix_pixel(screen,col,row,color);			// horizontal line
    		}
    	}
    }
    
    
    void copyscreen(unsigned long source[],unsigned long destination[])
    {
    	memcpy(destination,source,19200);					// a strings.h function
    }
    
    void color_demo(unsigned long screen[],char color_parameters[],int cognumber)					// kye graphics demo
    {
           pixenginestart(cognumber,cogject_color,screen,2,color_parameters);				// start the driver
           pix_pixel(screen,3,3,0x44);
    	pix_pixel(screen,4,4,0xFF);
    	pix_pixel(screen,5,5,pix_color(1,2,3));				// rgb each 0,1,2 or 3
    	pix_line(screen,0,0,159,119,pix_color(3,0,0));			// red border for screen
    	pix_colorbar(screen);						// a color bar
    	pix_line(screen,10,10,30,30,pix_color(3,3,0));		// a yellow box
    	pix_box_fill(screen,10,50,40,60,pix_color(3,0,3));		// magenta filled rectangle
    	//pix_readscreen("wallaby.vga",screen);				// display whole screen image 
    	//copyscreen(screen,screen_external);				// copy to external ram
    	//pix_readscreen("Giraffe.vga",screen);				// display whole screen image 
    	//copyscreen(screen_external,screen);				// copy back to hub
    	//pix_readscreen("prop160.vga",screen);				// display whole screen image
    	//pix_box_fill(screen, 0, 0, 159,119,pix_color(2,2,2));		// whole screen gray	
    }
    
    // ****************** end color screen code *********************************
    
    // ****************** begin gray screen code ********************************
    
    
    void gray_pixel(unsigned long screen[], unsigned long x, unsigned long y, unsigned long color)
    {
    	// unsigned long bitsperpixel = gray_parameters[3];
    	unsigned long bitsperpixel = 1;		// always is 1
    	unsigned long i;
    	i = (x >>4) + (20 * y);		// i = the long that contains our pixel	
           x = ((x & (0x1f >> bitsperpixel)) << bitsperpixel);
    	//mask = (0x3 << xpixel); 	// xpixel holds the number of bits to shift to the left, and invert this
    	//mask = ~mask;				// invert this
    	screen[i] = (( screen[i] & ~(0x3 << x)) | (color << x)); // do the and with a mask and the or in one line
    }
    
    int gray_printf(unsigned long screen[],int startx, int starty, char lineoftext[])
    {
    	int height = sans_serif_font[0] >> 8;			// read from the font data the height
    	int width,ascii,a,x,y,i,curx;
    	unsigned long font;
    	curx=startx;							// cursor
    	for(i=0;i<strlen(lineoftext);i++)				// get each letter in the string
    	{
    		ascii=lineoftext[i];
    		a=ascii * 13;						// calculate the address of the character
    		width = sans_serif_font[a] & 0x000000FF;		// mask out the height
    		for(y=0;y<height;y++)				// one row at a time
    		{
    			font=sans_serif_font[a+y+1];		// get the font long
    			for(x=0;x<width;x++)				// do each pixel
    			{
    				if((font & 0x00000001) == 1)	// test if a 1
    				{
    					gray_pixel(screen,curx+(width-1-x),starty+y,0x00);
    				}
    				font = font >> 1;			// shift in the next bit
    			}
    		}
    		curx += width;					// move cursor along by width amount
    	}
    	return curx-startx;						// return the width of all the text
    }
    
    void gray_debug_hex(unsigned long screen[],unsigned long hexnumber) // print a debug hex value on the screen at x=10, y=200
    {
    	int i,j;
    	char lineoftext[20];
    	for(j=0;j<12;j++)
    	{
    		for(i=4000;i<4006;i++)					// clear the previous text
    		{
    			screen[i+(20*j)]=0xaaaaaaaa;				// light gray
    			//screen[i+(20*j)]=0xffffffff;				// white
    
    		}
    	}
    	strcpy(lineoftext,hex(hexnumber));
    	gray_printf(screen,10,200,lineoftext);
    }
    
    void gray_debug_dec(unsigned long screen[],unsigned long decnumber) // print a debug decimal value on the screen at x=10, y=212
    {
    	int i,j;
    	char lineoftext[20];
    	for(j=0;j<12;j++)
    	{
    		for(i=4240;i<4246;i++)					// clear the previous text
    		{
    			screen[i+(20*j)]=0xaaaaaaaa;				// light gray
    			//screen[i+(20*j)]=0xffffffff;				// white
    		}
    	}
    	strcpy(lineoftext,str(decnumber));
    	gray_printf(screen,10,212,lineoftext);
    }
    
    void gray_horizontal_line(unsigned long screen[], int startx, int starty, int sizex, char color) 
    {
    	int col;	
    	for(col=startx;col <= startx+sizex ;col++)
    	{
    		gray_pixel(screen,col,starty,color);			// horizontal line
    	}
    }
    
    void gray_vertical_line(unsigned long screen[], int startx, int starty, int sizey, char color) 
    {
    	int row;	
    	for(row=starty;row <= starty+sizey;row++)
    	{
    		gray_pixel(screen,startx,row,color);			// vertical line
    	}
    }
    
    void gray_box_fill(unsigned long screen[], int startx, int starty, int sizex, int sizey, char color) 
    {
    	int row,col;
    	for(row =starty;row <= starty+sizey; row++)
    	{
    		for(col=startx;col <= startx+sizex; col++)
    		{
    			gray_pixel(screen,col,row,color);			// fill in pixels
    		}
    	}
    }
    
    void gray_groupbox(unsigned long screen[], int startx, int starty, int sizex, int sizey, char lineoftext[])
    {
    	int textwidth;
    	gray_horizontal_line(screen,startx,starty,10,0x1);						// dark gray horizontal line
    	gray_horizontal_line(screen,startx+1,starty+1,9,0x3);						// white horizontal line
    	gray_vertical_line(screen,startx,starty,sizey,0x1);						// dark gray vertical
    	gray_vertical_line(screen,startx+1,starty+1,sizey-1,0x3);					// white vertical
    	gray_horizontal_line(screen,startx,starty+sizey,sizex,0x1);					// dark gray horizontal line
    	gray_horizontal_line(screen,startx,starty+sizey+1,sizex+1,0x3);				// white horizontal line
    	gray_vertical_line(screen,startx+sizex,starty,sizey,0x1);					// dark gray vertical
    	gray_vertical_line(screen,startx+sizex+1,starty,sizey,0x3);					// white vertical
    	textwidth = gray_printf(screen, startx+14,starty-4,lineoftext);				// print the frame title
    	gray_horizontal_line(screen,startx+18+textwidth,starty,sizex-textwidth-18,0x1);		// dark gray horizontal line
    	gray_horizontal_line(screen,startx+18+textwidth,starty+1,sizex-textwidth-19,0x3);		// white horizontal line
    }
    
    void gray_button(unsigned long screen[],int startx, int starty, int sizex, int sizey, char lineoftext[])
    {
    	gray_vertical_line(screen, startx, starty, sizey, 0x3);					// white vertical line
    	gray_horizontal_line(screen, startx, starty, sizex, 0x3);					// white horizontal line
    	gray_vertical_line(screen, startx+sizex, starty+1, sizey-1, 0x1); 				// vertical dark gray line
    	gray_horizontal_line(screen, startx+1, starty+sizey, sizex, 0x1); 				// horizontal dark gray line
    	gray_vertical_line(screen, startx+sizex+1, starty, sizey+1, 0x0); 				// vertical black line
    	gray_horizontal_line(screen, startx, starty+sizey+1, sizex+1, 0x0); 				// horizontal black line
    	gray_printf(screen,startx+4,starty+4,lineoftext);						// print the button text
    }
    
    void gray_text(unsigned long screen[], int startx, int starty, int sizex, int sizey, char lineoftext[])
    {
    	gray_box_fill(screen, startx+1, starty+1, sizex-2, sizey-2,0x3);				// white centre
    	gray_vertical_line(screen, startx, starty, sizey-1, 0x0);					// black vertical line
    	gray_horizontal_line(screen, startx, starty, sizex-1,  0x0);					// black horizontal line
    	gray_vertical_line(screen, startx+sizex, starty+1, sizey,0x2); 				// vertical light gray line
    	gray_horizontal_line(screen, startx, starty+sizey, sizex, 0x2); 				// horizontal light gray line
    	gray_vertical_line(screen, startx-1, starty-1, sizey+1, 0x1);					// dark gray vertical line
    	gray_horizontal_line(screen, startx-1, starty-1, sizex+1, 0x1);					// dark gray horizontal line
    	gray_vertical_line(screen, startx+sizex+1, starty-1, sizey+2, 0x3);				// vertical whiteline
    	gray_horizontal_line(screen, startx-1, starty+sizey+1, sizex+1, 0x3);				// horizontal whiteline
    	gray_printf(screen,startx+2,starty+2,lineoftext);						// print the text
    }
    
    void gray_radio(unsigned long screen[], int startx, int starty, char check,char lineoftext[])
    {
    	char radio[144] = {				// black = 0x0, dark gray = 0x1, light gray = 0x2, white = 0x3
    	0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,	// a radio button
    	0x2,0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x2,
    	0x2,0x1,0x0,0x0,0x3,0x3,0x3,0x3,0x0,0x0,0x3,0x2,
    	0x2,0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,0x2,
    	0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,
    	0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,
    	0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,
    	0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,
    	0x2,0x1,0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x2,0x3,0x2,
    	0x2,0x1,0x2,0x2,0x3,0x3,0x3,0x3,0x2,0x2,0x3,0x2,
    	0x2,0x2,0x3,0x3,0x2,0x2,0x2,0x2,0x3,0x3,0x2,0x2,
    	0x2,0x2,0x2,0x2,0x3,0x3,0x3,0x3,0x2,0x2,0x2,0x2
    	};
    	int x;
    	int y;
    	int i = 0;
    	if(check !=0)
    	{
    		radio[53]=radio[54]=0x00;
    		radio[64]=radio[65]=radio[66]=radio[67]=0x00;		// draw the circle in the middle
    		radio[76]=radio[77]=radio[78]=radio[79]=0x00;
    		radio[89]=radio[90]=0x00;
    	}
    	for(y=0;y<12;y++)
    	{
    		for(x=0;x<12;x++)
    		{
    			gray_pixel(screen,startx+x, starty+y, radio[i]);	// draw a radio button, white centre
    			i++;
    		}
    	}
    	gray_printf(screen,startx+16,starty,lineoftext);			// print the text
    }
    
    void gray_mousepointer(unsigned long screen[],unsigned long mousebuffer[],int x, int y) 			// 21 high, 13 wide = 1 long wide 
    {
    	// mousebuffer 0-41 is the screen to restore, 42 is 0 for startup, 1 for redraw, 43 = oldx, 44=oldy
    	int i,j,n,m,r,s;
    	unsigned long pixels;
    	if (mousebuffer[42] ==1)								// restore. Skip first time if is zero
    	{
    		m=(mousebuffer[44]*20)+(mousebuffer[43]/16);				// oldy and oldx
    		for(i=0;i<21;i++)								// store the longs behind the mouse
    		{
    			screen[m]=mousebuffer[i];
    			screen[m+1]=mousebuffer[i+21];
    			m = m+20;
    		}
    	}
    	mousebuffer[42] = 1;									// always restore from now on
    	mousebuffer[43]=x;									// store current x
    	mousebuffer[44]=y;
    	n=0;
    	m=(y*20)+(x/16);									// get the screen long - 20 longs per row
    	r=x%16;										// work out the bitshift remainder - 16 pixels per long
    	//gray_debug_dec(screen,r);
    	for(i=0;i<21;i++)									// store the longs behind the mouse
    	{
    		mousebuffer[i]=screen[m];
    		mousebuffer[i+21]=screen[m+1];
    		m = m+20;
    	}
    	m=(y*20)+(x/16);									// recalculate m
    
    	if (r==0)										// no remainder so fits exactly in a long
    	{
    		for (i=0;i<21;i++)									// rows
    		{
    			{
    				screen[m] = screen[m] & mouse_mask[n];					// mask out pixel bits, ignore transparent bits
    				screen[m] = screen[m] | mouse_icon[n];					// draw the icon
    				n++;
    			}
    			m = m+20;									// next row
    		}
    	}
    	else
    											// bitshift so fits
    	{
    
    		s=r<<1;										// multiply by 2
    		for (i=0;i<21;i++)									// rows
    		{
    			{
    				// move mask and icon value into pixels. Shift. Leave bits on left as 11 for mask(transparent) and 00 for icon
    				// note also the order is reversed so shifts to the left move bits to the right. Very confusing!				
    				pixels = mouse_mask[n] << s;						// shift s=2 to 30 step 2
    				pixels = pixels | (0xffffffff >> (32-s));				// leave in transparent bits
    				screen[m] = screen[m] & pixels;					// mask out pixel bits, ignore transparent bits
    				pixels = mouse_mask[n] >> (32-s);						// shift in next long to the right	
    				pixels = pixels | (0xffffffff << s);
    				screen[m+1] = screen[m+1] & pixels;				// finished drawing the mask, now the icon
    				pixels = mouse_icon[n] << s;						// shift s=2 to 30 step 2
    				screen[m] = screen[m] | pixels;					// mask out pixel bits, ignore transparent bits
    				pixels = mouse_icon[n] >> (32-s);						// shift in next long to the right	
    				screen[m+1] = screen[m+1] | pixels;
    				n++;
    			}
    			m = m+20;									// next row
    		}
    
    	}
    }
    
    void gray_clearscreen(unsigned long screen[])
    {
    	int i;
    	for (i=0;i<4800;i++)
    	{
    		screen[i] = 0xaaaaaaaa;		// fill with light gray, use longs rather than bytes so 4 pixels per loop
    	}
    }
    
    void gray_engine_start(int cognumber, unsigned long cogarray[], unsigned long screen[], unsigned long gray_parameters[])
    {
    	unsigned long pingroup = 2;						// pins 16 to 23
    	int i;
    	unsigned long frequencystate;
    	gray_parameters[0] = 0xfca85400;				// pixelcolors in reverse order
    	gray_parameters[1] = 1;					// displayindicator
    	gray_parameters[2] = 0;					// syncindicator
    	gray_parameters[3] = 2;					// bitsperpixel, starts at 2 but gets changed later to 1
    	screen[0] = (unsigned long) &screen[0];			// the first long in the screen array now points to the location of itself
    	screen[1] = (unsigned long) &gray_parameters[1];	// pointer to displayindicator
    	screen[2] = (unsigned long) &gray_parameters[2];	// pointer to syncindicator
    	screen[3] = (0xff << (8*pingroup));
    	screen[4] = (0x200000ff | (pingroup << 9) | ((gray_parameters[3] -1) << 28));   // (0x200000ff | (pingroup << 9) | ((bitsperpixel-1) << 28)); this one not working
    	gray_parameters[3] = gray_parameters[3]  - 1;             // bitsperpixel now equal to 1, used below
    	frequencystate = ((25175000 + 1600) / 4);					// calculate frequencystate	 
    	screen[5] = 1;
    	for(i=0;i<32;i++)
    	{
    		frequencystate = frequencystate << 1;
    		screen[5] = (screen[5] << 1) | (screen[5] >> 31);
    		if (frequencystate >= _clockfreq())
    		{
    			frequencystate -= _clockfreq();
    			screen[5] += 1;
    		}
    	}
    	screen[6] = 2;						// horizontal scaling
    	screen[7] = 2;						// vertical scaling
    	screen[8] = 320;						// horizontal pixels
    	screen[9] = 240;						// vertical pixels
           screen[10] = ((screen[6] << 12) + (((640 * 32) >> gray_parameters[3] ) / screen[8])); // visible scale
    	screen[11] = (((8 << gray_parameters[3] ) << 12) + 160);	// invisible scale
           screen[12] = (screen[8] / (32 >> gray_parameters[3] ));	// horizongal longs
    	screen[13] = screen[12] * 4;				// horizontal loops
    	screen[14] = (unsigned long) &gray_parameters[0];	// pixel colors 
    	_cogstop(cognumber);							// stop graphics cog
    	external_memory_cog_load(cognumber,cogarray,screen);		// load from external ram to this cog, pass some values in screen[]
    	gray_clearscreen(screen);
    }
    
    void gray_demo(unsigned long screen[], unsigned long mousebuffer[], unsigned long gray_parameters[],unsigned long mouse_parameters[], int cognumber)
    {
    	unsigned long oldx,oldy = 1;						// previous mouse pointers, set to anything except 0 so draws the mouse on startup
    	gray_engine_start(cognumber,cogject_gray,screen,gray_parameters);
    	gray_debug_hex(screen,m_present());				// is the mouse present?
    	gray_printf(screen, 8,8,"File      Edit       Program");	// print menu text on the screen
    	gray_button(screen, 10, 40,50,19,"Button1");			// a button
    	gray_button(screen, 100,40,50,19,"Button2");			// a button
    	gray_text(screen, 10, 70, 70,16, "Textbox1");			// a text box
    	gray_text(screen, 100,70, 70,16, "Textbox2");			// a text box
    	gray_radio(screen, 10,100,1,"Radio1");				// a checked radio button
    	gray_radio(screen, 10,120,0,"Radio2");				// an unchecked radio button
    	gray_groupbox(screen,140,110,100,85,"GroupBox1");		// draw groupbox
           gray_printf(screen, 150,125,"Label1");				// print text on the screen
    	gray_printf(screen, 150,145,"Label2");				// print text on the screen
    	gray_printf(screen, 150,165,"Label3");				// print text on the screen
    	gray_printf(screen,10,186,"Debug value");
    //	gray_debug_hex(screen,123456);					// print a debug hex value on the screen at 10,200
    //	gray_debug_dec(screen,123456);
    //	gray_mousepointer(screen,mousebuffer,21,45);			// print a mouse pointer
    //	gray_mousepointer(screen,mousebuffer,25,48);			// move the mouse pointer
    	while(1)
    	{
    		if ((oldx != mouse_parameters[0]) | (oldy != mouse_parameters[1]))
    		{
    			gray_mousepointer(screen,mousebuffer,mouse_parameters[0]+160,120 - mouse_parameters[1]); // start in middle of screen
    			//gray_debug_hex(screen,mouse_parameters[0]);  // print the value
    			oldx = mouse_parameters[0];				// store the previous value
    			oldy = mouse_parameters[1];
    		}
    	}
    
    }
    
    void mouse_engine_start(int cognumber, unsigned long cogarray[], unsigned long mouse_parameters[], int dpin, int cpin)
    {
    	mouse_parameters[0] = (unsigned long) &mouse_parameters[0];	// the first long of the array points to the location of the array itself
    	mouse_parameters[5] = (unsigned long) dpin;			// data pin
    	mouse_parameters[6] = (unsigned long) cpin;
    	_cogstop(cognumber);							// stop this cog
    	external_memory_cog_load(cognumber,cogarray,mouse_parameters);			// load from external ram to this cog, pass location of the array
    	mouse_parameters[7] = 0;						// xmin
    	mouse_parameters[8] = 0;						// ymin
    	mouse_parameters[9] = 0;						// zmin
    	mouse_parameters[10] = 319;						// xmax
    	mouse_parameters[11] = 239;						// ymax
    	mouse_parameters[12] = 0;						// zmax
    
    }
    
    void main ()
    {
    	char color_parameters[1];						// displayindicator and syncindicater are permanent hub variables
    	unsigned long screen[4800];						// graphics and text video buffer in hub - eg 19200 bytes = 4800 longs
    	unsigned long gray_parameters[4];					// permanent hub variables for the gray 320x240 driver
    	unsigned long mousebuffer[45];					// pixels behind the mouse cursor 42 longs then some data
    	unsigned long mouse_parameters[19];				// group of 7 plus 12 longs in par_x in the spin version
    	int i;
    
    	mousebuffer[42] = 0;							// mouse 0 if startup, 1 if redraw
    	//m_bound_limits(0,300,0,0,220,0);					// set the mouse limits
    	text_clearscreen();							// white on blue vga clearscreen
           printf("Clock speed %u \n",_clockfreq());                     // see page 28 of the propeller manual for other useful commands
           printf("Catalina running in cog number %i \n",_cogid());      // integer
    	printf("Read vga color cogject into external ram array cogject_color\n");
    	readcog("vgagraph.cog",cogject_color);					// read in kye's graphics driver
    	printf("Read vga gray cogject into external ram array cogject_gray\n");
    	readcog("vga320.cog",cogject_gray);
    	printf("Read mouse cogject into external ram array cogject_mouse\n");
    	readcog("mouse.cog",cogject_mouse);
    	mouse_engine_start(7, cogject_mouse, mouse_parameters, 24, 25);	// start the mouse driver
    	printf("Finished reading cogjects into external ram \n");
    	_cogstop(3);								// stop cog 3 = one of the two default graphics cogs
    	color_demo(screen,color_parameters,1);				// start in cog 1 (stops cog 1 prior to restarting)
    	sleep(1000);								// so can see it
    	gray_demo(screen, mousebuffer, gray_parameters, mouse_parameters, 1);	// gray screen demo in cog 1
    	while (1); 								// endless loop as prop reboots on exit from main() 
    }
    
    
  • RossHRossH Posts: 5,519
    edited 2011-04-22 16:12
    RossH:
    By saying 'it is not fully ANSI C' I am referring to the source of Catalina that I have looked at, some of the extensions seem to be gcc style extensions. And my point in saying this is that Catalina can not be ported to every possible platform that has a C compiler with out first porting a different C compiler.

    Hi David,

    Catalina has no non-ANSI extensions. As for porting to another platform, it is not the C compiler that will constrain you, it is the availability of a PASM assembler. What platform did you have in mind?

    Ross.
  • RossHRossH Posts: 5,519
    edited 2011-04-22 16:21
    RossH:
    If Catalina will run well in not to much XMM, I think even that could be useful, assuming that the XMM driver can be easily modified by the user to use a variety of different memories, as not every one is going to have the same preferences, and many are likely to be adding there own memory to a board that comes with none.

    Hi David,

    Yes, at one stage I thought this would be true as well. But it turns out that almost no-one outside these forums (and very few within them) uses XMM to extend the memory capacity of the Propeller - so the number of potential users of a native Catalina compiler is fairly close to zero.

    However, if someone ever does write a fully functional SPIN/PASM compiler that runs natively on the Propeller (Sphinx is too limited), I may do it just for fun - porting the Catalina compiler and linker is a fairly simple exercise.

    Ross.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-22 16:25
    RossH wrote:
    What platform did you have in mind?
    Amiga 68K, Atari TT/Falcon (with out MiNT), Haiku OS, Amiga PowerPC, AROS, Minix, FreeDOS, MrOS, Symbian, and the other commonly used OSes that do not have any prop development tools, as well as the Prop.
  • RossHRossH Posts: 5,519
    edited 2011-04-22 16:29
    Dr_Acula wrote: »
    Back coding now. I thought I would tackle the graphical mouse next, mainly so I could answer the question as to whether Catalina is fast enough to draw and refresh a 273 pixel mouse pointer in real time. And the good news is that it can!
    Well done!
    Dr_Acula wrote: »

    At the moment I'm redrawing the mouse pointer from external ram but it probably would be faster again if the array was in hub ram.
    Yes, it would probaly be much faster.
    Dr_Acula wrote: »

    This code is not fully debugged - the bounds checking is not working so the mouse goes a bit haywire at the edges of the screen.

    It also demonstrates loading in another cogject (this program is now using 3 cogjects). I'm not sure if there is a "right" or "wrong" method in terms of plugins vs cogjects and I guess I would like to see both methods available for use. What is nice though is to be able to use the same cogject for a spin program and a C program.
    There is not really a "right" or "wrong" way. I would like to encourage the use of plugins because it will make it much simpler for others to follow in your footsteps - but it may indeed make your job slightly harder!
    Dr_Acula wrote: »

    I have found that the sd card driver in Catalina is a little slow compared with Kye's SD driver. For the moment, the optimum speed solution is to load all cogjects into XMM at bootup, as it is faster to load a cogject from XMM into a cog than it is to load from SD into cog. That could change down the track.

    Yes, I'm aware of this one. It's on my list of things to do at some point. It may even be possible to do a fairly simple drop in replacement - if someone else wants to look a this, feel free to do so!

    Ross.
  • RossHRossH Posts: 5,519
    edited 2011-04-22 17:05
    Amiga 68K, Atari TT/Falcon (with out MiNT), Haiku OS, Amiga PowerPC, AROS, Minix, FreeDOS, MrOS, Symbian, and the other commonly used OSes that do not have any prop development tools, as well as the Prop.

    Hi David,

    Your first step to adding Propeller support to any platform is porting a PASM assembler. You can live without a SPIN compiler when compiling Catalina XMM programs since the current reconfigurable SPIN targets can be entirely replaced by a set of precompiled binary targets specific to each target Propeller platform - but you can't get by without a PASM assembler since Catalina generates PASM as output.

    If you don't have an ANSI C compiler on your platform, then the next step is to port a self-hosted C compiler (remember, Catalina is a cross-compiler) - but that compiler can be LCC itself (which can be either). Compiler bootstrapping techniques are described here: http://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 - but the cost of doing this for each specific platform is going to be high, and would normally only be contemplated by a vendor (who expects to recoup the cost by selling product).

    The final (and easiest!) step is porting Catalina itself. This is simply a matter of compiling it using the self-hosted C compiler. Catalina currently compiles with gcc, but I have in the past compiled it with lcc, and it should compile correctly with any ANSI C compiler.

    Ross.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-04-22 17:07
    Sphinx does work on a single Prop with an SD card, keyboard, and TV display. It can compile itself and, like other Prop Tools, includes an assembler. There's also a simple compiler-compiler called Meta2 which is optimized to produce Spin source and compiles itself using Sphinx. Meta2 was used many years ago to bootstrap an AlgolW compiler for the PDP-10 and a Pascal compiler for the Datapoint 5500.

    Issues include the lack of a good editor for the Prop (there's a minimal one that's part of Sphinx), the limitations of a TV display, and tight memory constraints for the Prop. A two Prop system could be used to offload the I/O including a reasonably wide VGA display yet not impacting the available memory for the compiler. There are 64 and 80 column TV drivers available as well that could be used in an I/O Prop. The various tables (like the symbol table) could be kept on the SD card with caching used to reduce the speed impact of not keeping them resident.

    C could probably be bootstrapped through such a system, maybe producing Spin bytecodes initially, then later using a customized Spin interpreter that might use some LMM and some native overlays for speed.

    Porting Catalina to the Prop by cross compiling does have a lot of advantages since you can produce LMM and XMM programs. It would be a preferred path for use with the Prop II because of the increased native memory and better support for external memory.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-04-22 17:16
    Sphinx does work on a single Prop with an SD card, keyboard, and TV display. It can compile itself and, like other Prop Tools, includes an assembler. There's also a simple compiler-compiler called Meta2 which is optimized to produce Spin source and compiles itself using Sphinx. Meta2 was used many years ago to bootstrap an AlgolW compiler for the PDP-10 and a Pascal compiler for the Datapoint 5500.

    Issues include the lack of a good editor for the Prop (there's a minimal one that's part of Sphinx), the limitations of a TV display, and tight memory constraints for the Prop. A two Prop system could be used to offload the I/O including a reasonably wide VGA display yet not impacting the available memory for the compiler. There are 64 and 80 column TV drivers available as well that could be used in an I/O Prop. The various tables (like the symbol table) could be kept on the SD card with caching used to reduce the speed impact of not keeping them resident.

    C could probably be bootstrapped through such a system, maybe producing Spin bytecodes initially, then later using a customized Spin interpreter that might use some LMM and some native overlays for speed.
  • RossHRossH Posts: 5,519
    edited 2011-04-22 17:38
    Mike Green wrote: »
    Sphinx does work on a single Prop with an SD card, keyboard, and TV display. It can compile itself and, like other Prop Tools, includes an assembler.

    ...

    C could probably be bootstrapped through such a system, maybe producing Spin bytecodes initially, then later using a customized Spin interpreter that might use some LMM and some native overlays for speed.

    Hi Mike,

    True. However, while I haven't looked at Sphinx recently, the early versions were way too limited (size-wise). Compiling a C program to PASM, and then using Sphinx to compile the PASM would be fairly certain to blow Sphinx's capacity just on the C symbol table alone - compilers tend to generate many more symbols than the equivalent hand-coded PASM would need.

    From memory you need 64 characters for the name of each symbol to conform to the ANSI C standard (not to mention whatever other data you need to store about each symbol, such as its type and value). This means in 32k you could never have more than a few hundred symbols. But a compiler typically generates dozens of symbols for each C function, so you would probably find yourself runing out of memory space after defining just a few functions.

    In the very early versions of Catalina I used the Parallax compiler as my PASM compiler, but I very quickly ran into all sorts of limits like this and had to move to a SPIN/PASM compiler with larger capacity. Thank goodness for bst and Homespun!

    But an LMM version of Sphinx would probably overcome this particular problem - any volunteers?

    Ross.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-22 19:10
    From memory you need 64 characters for the name of each symbol to conform to the ANSI C standard
    Has ANSI C changed since I last read up on it??
    ANSI C only requires that the first 6 characters of a symbol be significant, ANSI C does not include the '//' remark symbol (although most compilers due), and ANSI C does not require any libs beyond stdio (even though it does RECOMMEND others), as such not all ANSI C compilers provide all the recommended libs. And I am aware that ANSI C does RECOMMEND (though NOT require) that internal symbols be handled with the first 32 characters significant. As to types, these should not show up as symbols in assembly. Though I do thank you for your recommendations on compiling Catalina on other platforms.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-04-22 21:26
    RossH,
    Meta2 has its own symbol table so it can keep various attributes of the symbols around to control compilation. Typically, the output uses generated symbols or the meta-compiler does its own storage allocation for data variables and those symbols never make it into the generated Spin code. The current version uses a 32K section of a 128K EEPROM for the symbol table. Each entry is rarely changed once written, so a compilation doesn't have much effect on EEPROM wear-out.
  • RossHRossH Posts: 5,519
    edited 2011-04-23 06:40
    Has ANSI C changed since I last read up on it??
    ANSI C only requires that the first 6 characters of a symbol be significant, ANSI C does not include the '//' remark symbol (although most compilers due), and ANSI C does not require any libs beyond stdio (even though it does RECOMMEND others), as such not all ANSI C compilers provide all the recommended libs. And I am aware that ANSI C does RECOMMEND (though NOT require) that internal symbols be handled with the first 32 characters significant. As to types, these should not show up as symbols in assembly. Though I do thank you for your recommendations on compiling Catalina on other platforms.

    Hi David,

    I think you'll find it has changed quite a lot. C89 standardized many things, and C99 extended the standard a little more. I shouldn't really say "ANSI C" without being more specific, but it is a convenient shorthand that seems to be generally understood.

    ANSI C now allows 6 characters is for external identifiers only. it requires a minimum of 32 characters for internal identifiers. However, since the Propeller assembler is not case sensitive (but C identifiers are) it turns out you need up to 64 characters to represent each C identifer in PASM.

    ANSI C includes the // in C99 - but it is a common extension for C89 compilers to include it as well.

    ANSI C requires a full suite of libraries in addition to stdio - the minimum C89 set also includes assert, ctype, errno, float, locale, math, stdlib, stdarg, string, time, setjmp, signal & stddef. C99 adds a few more, some of which are included with Catalina (but Catalina is really only C89 compliant).

    It's true that types will not appear in the final assembly code, but they certainly appear in the symbol table, along with all the other symbols that need to be tracked during a compilation, such as variables, functions & labels. These may be user or compiler generated, and in some cases (particularly labels) the compiler will typically generate many, many more of them than the user ever defines (this is where I ran into problems with the Parallax tools!). Also, types will appear in the debugger output that is associated with the program, since the debugger needs to know about them.

    Ross.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-04-23 06:51
    RossH:
    Thank you. I am familiar with the rules laid down in C89, while I am aware of C99, I did not realize that it changed that much.
    A couple of thoughts:
    With the prop assemblers net being case sensitive, would it not be more efficient to compile directly to binary? Also is there a reason to use a multi-pass compiler for the prop, does optimization provided in this way actually make a difference on the Propeller?
    Perhaps a K&R C subset Catalina compiler is in order (with the extensions on function declaration, and void)?
  • RossHRossH Posts: 5,519
    edited 2011-04-23 06:52
    Mike Green wrote: »
    RossH,
    Meta2 has its own symbol table so it can keep various attributes of the symbols around to control compilation. Typically, the output uses generated symbols or the meta-compiler does its own storage allocation for data variables and those symbols never make it into the generated Spin code. The current version uses a 32K section of a 128K EEPROM for the symbol table. Each entry is rarely changed once written, so a compilation doesn't have much effect on EEPROM wear-out.

    Hi Mike,

    Intriguing - I'll have to check it out. You say Meta2 can compile itself using Sphinx, but I'm not sure if that means that you are guaranteed that the output of Meta2 will aways be compilable with Sphinx. I know Sphinx does not implement the full SPIN language, but I'm not really sure just how much of Spin you would have to avoid (or how you would do so) when using Meta2 to generate the Spin code. Is this likely to be a problem?

    Ross.
  • RossHRossH Posts: 5,519
    edited 2011-04-23 07:08
    With the prop assemblers net being case sensitive, would it not be more efficient to compile directly to binary?
    Not really - not unless you also want to define your own object format and also write your own binary linker. Catalina sidesteps all these issues quite neatly by binding the program components together at the source level rather than the binary level. This saves a heck of a lot of work.
    Also is there a reason to use a multi-pass compiler for the prop, does optimization provided in this way actually make a difference on the Propeller?
    Yes it does. Without the kind of optimization a multi-pass compiler can easily do, I'd estimate the code size would go up by 50% - possibly more in some cases. Catalina could really do with more optimization, not less!
    Perhaps a K&R C subset Catalina compiler is in order (with the extensions on function declaration, and void)?
    Please, no! It took 20 years to get C into reasonable shape - who'd want to go back to the days where every C compiler you ever used was slightly different?

    Ross.
Sign In or Register to comment.