blog:x68_devcode

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
blog:x68_devcode [2020/07/12 12:40] johnblog:x68_devcode [2020/08/07 21:22] (current) – [X68000 C Code Examples] john
Line 1: Line 1:
-====== X68000 C Code Examples ======+====== Sharp X68000 C Code Examples ======
  
 Here are some example code listings to compile and run on the Sharp X68000. They demonstrate how to use some of the built-in system calls. Here are some example code listings to compile and run on the Sharp X68000. They demonstrate how to use some of the built-in system calls.
Line 5: Line 5:
 All of the samples on this page will compile and run with the [[blog:x68_devtools#the_Lydux_toolchain_gCC_462|Lydux GCC 4.6.2]] toolchain. All of the samples on this page will compile and run with the [[blog:x68_devtools#the_Lydux_toolchain_gCC_462|Lydux GCC 4.6.2]] toolchain.
  
-//Remember, the X68000 is a big-endian machine, so all integers in memory are in reverse byte order compared to x86!//+//Remember, the Sharp X68000 is a big-endian machine using the Motorola 68000 or 68030, so all integers in memory are in reverse byte order compared to Intel/AMD x86 and x86_64!//
  
 ---- ----
Line 326: Line 326:
    * In 4bit mode, only the lower 4 bits of a //uint16_t// is used.    * In 4bit mode, only the lower 4 bits of a //uint16_t// is used.
  
 +//Remember that all pixel data values are big-endian numbers!//
 ==== Converting RGB values to X68000 GRB+i ==== ==== Converting RGB values to X68000 GRB+i ====
  
Line 370: Line 371:
  
 ==== Changing Screen Mode ==== ==== Changing Screen Mode ====
 +
 +Most graphics hardware operations are performed through system calls access via the //iocs// functions. With the Lydux GCC toolchain these are listed in the file: **/opt/toolchains/x68k/human68k/include/iocs.h** - if you are on Windows, or have compiled up the toolchain yourself from source, the location will of course be different.
 +
 +These tiny wrappers map the X68000 BIOS/ROM calls to C functions. Things like: clear graphics screen, set video mode, scroll screen region etc.
 +
 +The process to set and change to a new screen mode is refreshingly simple on the X68000 compared to a lot of other machines (the x86 and DOS!).
 +
 +The process is:
 +   * (optionally) Save current screen mode setting
 +   * Set the new screen mode
 +   * Set at least one graphics page to be active
 +   * (optionally) clear the graphics page
 +   * (optionally) turn text cursor off
 +
 +To return to the previous screen mode is basically the same in reverse.
  
 <code C> <code C>
Line 416: Line 432:
 ... you can see that <code>_iocs_crtmod(8);</code> sets the screen to be 512 x 512 in 256 colour //and// provides two such screens (double buffering?). You can even have mode 12; a 16bit screen on 512 x 512 in 65536 colour, that's a pretty spectacular screen mode for a machine dating from 1987! ... you can see that <code>_iocs_crtmod(8);</code> sets the screen to be 512 x 512 in 256 colour //and// provides two such screens (double buffering?). You can even have mode 12; a 16bit screen on 512 x 512 in 65536 colour, that's a pretty spectacular screen mode for a machine dating from 1987!
  
 +It does have some really nice screen modes, down towards the bottom of the list, but you should be aware that these are only supported in machines which have a later BIOS/ROM (or IPL in X68000 speak), so you cannot rely on them being available on all machines.
 +
 +Specifically, (according to the PUNI documentation - and Inside X68000 manual) **mode 19** (640x480) is only available on X68000 models with ROM IOCS 1.2 or higher, and **modes 20-27** are only available on machines with ROM IOCS 1.3 or higher... I can't tell you which models (Ace, Super, Expert, Pro, XVI, Compact, 030) that means as I don't know. Best stick with screen modes //under// **mode 19**.
 +
 +==== XY Screen coordinates to GVRAM address ====
 +
 +The GVRAM on the Sharp X68000 is arranged in such a way that the starting address of a given video page is always the top left corner of the screen (usually x=0, y=0). With the last address of a given video page being the bottom right corner (x=511, y=511 on a 512x512 resolution video mode).
 +
 +With this in mind, and the fact that every pixel on a X68000 GVRAM video screen taking exactly 2 bytes, we can plot xy coordinates to specific GVRAM addresses quite easily (and we'll need to do so in order to accurately place elements on the screen).
 +
 +<code C>
 +#define GVRAM_START 0xC00000 // Start of graphics vram for this video page
 +#define GVRAM_END 0xC7FFFF // End of graphics vram for this video page
 +
 +int gvramGetXYaddr(int x, int y){
 + // Return the memory address of an X,Y screen coordinate based on the GFX_COLS and GFX_ROWS
 + // as defined in gfx.h - if you define a different screen mode dynamically, this WILL NOT WORK
 +
 + uint32_t addr;
 + uint16_t row;
 +
 + // This could be a one liner, but without hardware multiplication, perhaps
 + // its better to stick to an addition loop?
 + addr = GVRAM_START;
 +
 + for(row = 0; row < y; row++){   // We are really doing GFX_ROW_SIZE * y
 + addr += GFX_ROW_SIZE;
 + }
 + addr += (x * GFX_PIXEL_SIZE);
 +
 + if (GFX_VERBOSE){
 + printf("%s.%d\t x:%03d y:%03d gvram:%08x\n", __FILE__, __LINE__, x, y, (unsigned int) addr);
 + }
 +
 + if (addr>GVRAM_END){
 + if (GFX_VERBOSE){
 + printf("%s.%d\t XY coords beyond GVRAM address range\n", __FILE__, __LINE__);
 + }
 + }
 + return addr;
 +}
 +</code>
 +
 +This will return an address that can be used to reassign the current GVRAM pointer (//uint16_t *gvram;//) to the coordinates which have been specified.
 +
 +Note:
 +   * It needs profiling whether //GFX_COLS * y// is faster or slower than multiple additions of //GFX_COLS//. On a FPU-less microprocessor like the 68000, it could be the latter. I'm not sure yet.
 ==== Filling the screen with pixels in GVRAM ==== ==== Filling the screen with pixels in GVRAM ====
  
Line 645: Line 708:
 ---- ----
  
-==== XY Screen coordinates to GVRAM address ==== 
  
-The GVRAM on the Sharp X68000 is arranged in such a way that the starting address of a given video page is always the top left corner of the screen (usually x=0, y=0). With the last address of a given video page being the bottom right corner (x=511, y=511 on a 512x512 resolution video mode). 
- 
-With this in mind, and the fact that every pixel on a X68000 GVRAM video screen taking exactly 2 bytes, we can plot xy coordinates to specific GVRAM addresses quite easily (and we'll need to do so in order to accurately place elements on the screen). 
- 
-<code C> 
-#define GVRAM_START 0xC00000 // Start of graphics vram for this video page 
-#define GVRAM_END 0xC7FFFF // End of graphics vram for this video page 
- 
-int gvramGetXYaddr(int x, int y){ 
- // Return the memory address of an X,Y screen coordinate based on the GFX_COLS and GFX_ROWS 
- // as defined in gfx.h - if you define a different screen mode dynamically, this WILL NOT WORK 
-  
- uint32_t addr; 
- uint16_t row; 
-  
- // This could be a one liner, but without hardware multiplication, perhaps 
- // its better to stick to an addition loop? 
- addr = GVRAM_START; 
- 
- for(row = 0; row < y; row++){   // We are really doing GFX_ROW_SIZE * y 
- addr += GFX_ROW_SIZE; 
- } 
- addr += (x * GFX_PIXEL_SIZE); 
-  
- if (GFX_VERBOSE){ 
- printf("%s.%d\t x:%03d y:%03d gvram:%08x\n", __FILE__, __LINE__, x, y, (unsigned int) addr);  
- } 
-  
- if (addr>GVRAM_END){ 
- if (GFX_VERBOSE){ 
- printf("%s.%d\t XY coords beyond GVRAM address range\n", __FILE__, __LINE__); 
- } 
- } 
- return addr; 
-} 
-</code> 
- 
-This will return an address that can be used to reassign the current GVRAM pointer (//uint16_t *gvram;//) to the coordinates which have been specified. 
- 
-Note: 
-   * It needs profiling whether //GFX_COLS * y// is faster or slower than multiple additions of //GFX_COLS//. On a FPU-less microprocessor like the 68000, it could be the latter. I'm not sure yet. 
  
 ==== Loading 16bit RGB Bitmap from Disk ==== ==== Loading 16bit RGB Bitmap from Disk ====
Line 1169: Line 1190:
 } }
 </code> </code>
 +
 +If this is called as follows:
 +
 +<code C>
 +red = rgb888_2grb(0xFF, 0x00, 0x00, 1);
 +gvramPoint(0, 0, red);
 +gvramPoint(10, 10, red);
 +gvramPoint(25, 25, red);
 +gvramPoint(100, 100, red);
 +gvramPoint(250, 250, red);
 +gvramPoint(350, 350, red);
 +gvramPoint(500, 500, red);
 +gvramPoint(511, 511, red);
 +</code>
 +
 +This should generate output of a sequence of 8 red pixels along a diagonal line from 0,0 to 511,511:
 +
 +{{:blog:x68000_points.png?600|}}
 +
 +You may need to click this image to see the points successfully.
  
 ---- ----
Line 1246: Line 1287:
 </code> </code>
  
-Note, this draw an outline of a rectangle only. For filled rectangles, look below...+If you call the function as follows: 
 + 
 +<code C> 
 +int red, orange, green, blueish; 
 + 
 +red = rgb888_2grb(0xFF, 0x00, 0x00, 1); 
 +orange = rgb888_2grb(0xFF, 0xB0, 0x0F, 1); 
 +green = rgb888_2grb(0x00, 0xFF, 0x00, 1); 
 +blueish = rgb888_2grb(0x00, 0x00, 0xEE, 1); 
 + 
 +gvramBox(0, 50, 100, 100, red); 
 +gvramBox(1, 100, 101, 150, red); 
 +gvramBox(3, 200, 103, 250, orange); 
 +gvramBox(275, 450, 500, 500, green); 
 +gvramBox(75, 300, 200, 305, blueish); 
 +</code> 
 + 
 +You should see the following: 
 + 
 +{{:blog:x68000_rectangles.png?600|}} 
 + 
 +Note, this draws an outline of a rectangle only. For filled rectangles, look below...
  
 ---- ----
Line 1308: Line 1370:
 } }
 </code> </code>
 +
 +If the function is called as follows:
 +
 +<code C>
 +int red, greyish, blue, pinkish, orange;
 +
 +red = rgb888_2grb(0xFF, 0xFF, 0xFF, 1);
 +greyish = rgb888_2grb(0xDD, 0xFF, 0xEE, 1);
 +blue = rgb888_2grb(0x00, 0x00, 0xEE, 1);
 +pinkish = rgb888_2grb(0xF0, 0x19, 0xAF, 1);
 +orange = rgb888_2grb(0xFF, 0xB0, 0x0F, 1);
 +
 +gvramBoxFill(0, 0, 30, 30, red);
 +gvramBoxFill(200, 10, 230, 300, red);
 +gvramBoxFill(300, 210, 400, 255, orange);
 +gvramBoxFill(489, 300, 510, 510, pinkish);
 +gvramBoxFill(50, 400, 320, 500, blue);
 +gvramBoxFill(0, 500, 75, 525, greyish);    // This one should be clipped at y axis
 +gvramBoxFill(1, 1, 31, 31, greyish);       // This one should partially obscure the red rectangle at 0,0
 +</code>
 +
 +This should display output as follows:
 +
 +{{:blog:x68000_rectangles_filled.png?600|}}
  
 ---- ----
Line 1418: Line 1504:
  
 ===== TVRAM Operations ===== ===== TVRAM Operations =====
 +
 +TVRAM (or Text-RAM) is another area of video RAM on the X68000, distinctly seperate from the previous GVRAM we looked at above.
 +
 +Text RAM is again accessed via a memory mapped address range in the X68000 address space.
 +
 +1 Row 128 bytes(64 words)
 +
 +^ Page ^ Address Range       ^
 +| 0    | 0xE00000 - 0xE1FFFF |
 +| 1    | 0xE20000 - 0xE3FFFF |
 +| 2    | 0xE40000 - 0xE5FFFF |
 +| 3    | 0xE60000 - 0xE7FFFF |
 +
 +Unlike GVRAM where one pixel was directly mapped to a single memory location (writing a 16bit value to //0xC00000// would set the colour of a single pixel at screen position 0,0), [[https://en.wikipedia.org/wiki/Planar_(computer_graphics)|Text RAM is planar]]. 
 +
 +Writing a 16bit value to //0xE00000// will actually turn on and off the first 16 bits of row 0 of the screen.
 +
 +For example; suppose you write the 16bit value 0xFFFF (bits: 1111111111111111), to 0xE00000. You'll get a line of 16 pixels turned on:
 +
 +{{:blog:x68000_text_ffff.png?200|}}
 +
 +If you write the value 0xAAAA (a pattern of: 1010101010101010) to 0xE00000 you instead get an alternating pattern of pixels on and off:
 +
 +{{:blog:x68000_text_aaaa.png?200|}}
 +
 +Writing another 16bit value to 0xE20000, 0xE40000 and 0xE60000 will result in the bit patterns being overlaid and generating a different colour for those first 16 pixels.
 +
 +Using this planar arrangement means you only need to write 64 x 16bit words to set every pixel in a row to be on or off... of course if you want them to be different colours you then need to write other patterns to the other text planes. It's swings and roundabouts to trade off.
 +
 +TO-DO - further explanation of how the colour of the pixels is determined (palette lookup).
  
 ---- ----
  
 ===== Sprite Operations ===== ===== Sprite Operations =====
  • blog/x68_devcode.1594554029.txt.gz
  • Last modified: 2020/07/12 12:40
  • by john