diff --git a/src/main/kc/include/atari-xl.h b/src/main/kc/include/atari-xl.h index c28363161..9f3a707b1 100644 --- a/src/main/kc/include/atari-xl.h +++ b/src/main/kc/include/atari-xl.h @@ -1,6 +1,10 @@ // Atari 8-bit 400/800/XL/XE Registers and Constants // https://en.wikipedia.org/wiki/Atari_8-bit_family +#ifndef __ATARIXL__ +#error "Target platform must be atarixl" +#endif + #include #include #include diff --git a/src/main/kc/include/atari2600.h b/src/main/kc/include/atari2600.h index 1572befc2..8137a0cbd 100644 --- a/src/main/kc/include/atari2600.h +++ b/src/main/kc/include/atari2600.h @@ -1,6 +1,10 @@ // Atari 2600 Registers and Constants // https://web.archive.org/web/20170215054248/http://www.atariguide.com/pdfs/Atari_2600_VCS_Domestic_Field_Service_Manual.pdf +#ifndef __ATARI2600__ +#error "Target platform must be atari2600" +#endif + #include #include diff --git a/src/main/kc/include/cx16-vera.h b/src/main/kc/include/cx16-vera.h index 696ae090d..6ffb576a4 100644 --- a/src/main/kc/include/cx16-vera.h +++ b/src/main/kc/include/cx16-vera.h @@ -1,6 +1,24 @@ // Commander X16 VERA (Versatile Embedded Retro Adapter) Video and Audio Processor // https://github.com/commanderx16/x16-docs/blob/master/VERA%20Programmer's%20Reference.md +// The colors of the CX16 +const char BLACK = 0x0; +const char WHITE = 0x1; +const char RED = 0x2; +const char CYAN = 0x3; +const char PURPLE = 0x4; +const char GREEN = 0x5; +const char BLUE = 0x6; +const char YELLOW = 0x7; +const char ORANGE = 0x8; +const char BROWN = 0x9; +const char PINK = 0xa; +const char DARK_GREY = 0xb; +const char GREY = 0xc; +const char LIGHT_GREEN = 0xd; +const char LIGHT_BLUE = 0xe; +const char LIGHT_GREY = 0xf; + // To access the VRAM (which is 128kB in size) an indirection mechanism is used. // First the address to be accessed needs to be set (ADDRx_L/ADDRx_M/ADDRx_H) and // then the data on that VRAM address can be read from or written to via the DATA0/1 register. @@ -36,6 +54,22 @@ const char VERA_INC_80 = 0xc0; const char VERA_INC_160 = 0xd0; const char VERA_INC_320 = 0xe0; const char VERA_INC_640 = 0xf0; +const char VERA_DECR_0 = 0x08; +const char VERA_DECR_1 = 0x18; +const char VERA_DECR_2 = 0x28; +const char VERA_DECR_4 = 0x38; +const char VERA_DECR_8 = 0x48; +const char VERA_DECR_16 = 0x58; +const char VERA_DECR_32 = 0x68; +const char VERA_DECR_64 = 0x78; +const char VERA_DECR_128 = 0x88; +const char VERA_DECR_256 = 0x98; +const char VERA_DECR_512 = 0xa8; +const char VERA_DECR_40 = 0xb8; +const char VERA_DECR_80 = 0xc8; +const char VERA_DECR_160 = 0xd8; +const char VERA_DECR_320 = 0xe8; +const char VERA_DECR_640 = 0xf8; // $9F23 DATA0 VRAM Data port 0 char * const VERA_DATA0 = 0x9f23; // $9F24 DATA1 VRAM Data port 1 @@ -81,14 +115,14 @@ char * const VERA_IRQLINE_L = 0x9f28; // Bit 2: Chroma Disable Setting 'Chroma Disable' disables output of chroma in NTSC composite mode and will give a better picture on a monochrome display. (Setting this bit will also disable the chroma output on the S-video output.) // Bit 0-1: Output Mode 0: Video disabled, 1: VGA output, 2: NTSC composite, 3: RGB interlaced, composite sync (via VGA connector) char * const VERA_DC_VIDEO = 0x9f29; -char VERA_SPRITES_ENABLE = 0x40; -char VERA_LAYER1_ENABLE = 0x20; -char VERA_LAYER0_ENABLE = 0x10; -char VERA_CROMA_DISABLE = 0x04; -char VERA_OUTPUT_DISABLE = 0x00; -char VERA_OUTPUT_VGA = 0x01; -char VERA_OUTPUT_NTSC = 0x02; -char VERA_OUTPUT_RGB = 0x03; +const char VERA_SPRITES_ENABLE = 0x40; +const char VERA_LAYER1_ENABLE = 0x20; +const char VERA_LAYER0_ENABLE = 0x10; +const char VERA_CROMA_DISABLE = 0x04; +const char VERA_OUTPUT_DISABLE = 0x00; +const char VERA_OUTPUT_VGA = 0x01; +const char VERA_OUTPUT_NTSC = 0x02; +const char VERA_OUTPUT_RGB = 0x03; // $9F2A DC_HSCALE (DCSEL=0) Active Display H-Scale char * const VERA_DC_HSCALE = 0x9f2a; // $9F2B DC_VSCALE (DCSEL=0) Active Display V-Scale @@ -110,6 +144,29 @@ char * const VERA_DC_VSTOP = 0x9f2c; // Bit 2: Bitmap Mode (0:tile mode, 1: bitmap mode) // Bit 0-1: Color Depth (0: 1 bpp, 1: 2 bpp, 2: 4 bpp, 3: 8 bpp) char * const VERA_L0_CONFIG = 0x9f2d; +// Layer Configuration Bit 6-7: Map Height (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles) +char const VERA_CONFIG_HEIGHT_32 = 0x00; +char const VERA_CONFIG_HEIGHT_64 = 0x40; +char const VERA_CONFIG_HEIGHT_128 = 0x80; +char const VERA_CONFIG_HEIGHT_256 = 0xC0; +char const VERA_CONFIG_HEIGHT_MASK = 0xC0; +// Layer Configuration Bit 4-5. Map Width (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles) +char const VERA_CONFIG_WIDTH_32 = 0x00; +char const VERA_CONFIG_WIDTH_64 = 0x10; +char const VERA_CONFIG_WIDTH_128 = 0x20; +char const VERA_CONFIG_WIDTH_256 = 0x30; +char const VERA_CONFIG_WIDTH_MASK = 0x30; +// Layer Configuration Bit 3: T256C (0: tiles use a 16-color foreground and background color, 1: tiles use a 256-color foreground color) (only relevant in 1bpp modes) +char const VERA_CONFIG_16C = 0x00; +char const VERA_CONFIG_256C = 0x08; +// Layer Configuration Bit 2: Bitmap Mode (0:tile mode, 1: bitmap mode) +char const VERA_CONFIG_MODE_TILE = 0x00; +char const VERA_CONFIG_MODE_BITMAP = 0x04; +// Layer Configuration Bit 0-1: Color Depth (0: 1 bpp, 1: 2 bpp, 2: 4 bpp, 3: 8 bpp) +char const VERA_CONFIG_COLOR_1BPP = 0x00; +char const VERA_CONFIG_COLOR_2BPP = 0x01; +char const VERA_CONFIG_COLOR_4BPP = 0x02; +char const VERA_CONFIG_COLOR_8BPP = 0x03; // $9F2E L0_MAPBASE Layer 0 Map Base Address (16:9) char * const VERA_L0_MAPBASE = 0x9f2e; // $9F2F L0_TILEBASE Layer 0 Tile Base @@ -125,7 +182,6 @@ char * const VERA_L0_HSCROLL_H = 0x9f31; char * const VERA_L0_VSCROLL_L = 0x9f32; // $9F33 L0_VSCROLL_H Layer 0 V-Scroll (11:8) char * const VERA_L0_VSCROLL_H = 0x9f33; -// $9F34 L1_CONFIG Layer 1 Configuration // Bit 6-7: Map Height (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles) // Bit 4-5. Map Width (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles) // Bit 3: T256C (0: tiles use a 16-color foreground and background color, 1: tiles use a 256-color foreground color) (only relevant in 1bpp modes) diff --git a/src/main/kc/include/cx16.h b/src/main/kc/include/cx16.h index 497e56fde..fc089da43 100644 --- a/src/main/kc/include/cx16.h +++ b/src/main/kc/include/cx16.h @@ -1,7 +1,9 @@ // Commander X16 // https://www.commanderx16.com/forum/index.php?/about-faq/ // https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md - +#ifndef __CX16__ +#error "Target platform must be cx16" +#endif #include #include @@ -61,3 +63,16 @@ char vpeek(char vbank, char* vaddr); // - src: The source address in RAM // - num: The number of bytes to copy void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num ); + +// Copy block of memory (from VRAM to VRAM) +// Copies the values from the location pointed by src to the location pointed by dest. +// The method uses the VERA access ports 0 and 1 to copy data from and to in VRAM. +// - src_bank: 64K VRAM bank number to copy from (0/1). +// - src: pointer to the location to copy from. Note that the address is a 16 bit value! +// - src_increment: the increment indicator, VERA needs this because addressing increment is automated by VERA at each access. +// - dest_bank: 64K VRAM bank number to copy to (0/1). +// - dest: pointer to the location to copy to. Note that the address is a 16 bit value! +// - dest_increment: the increment indicator, VERA needs this because addressing increment is automated by VERA at each access. +// - num: The number of bytes to copy +void memcpy_in_vram(char dest_bank, void *dest, char dest_increment, char src_bank, void *src, char src_increment, unsigned int num ); + diff --git a/src/main/kc/include/veralib.h b/src/main/kc/include/veralib.h new file mode 100644 index 000000000..ac0c72595 --- /dev/null +++ b/src/main/kc/include/veralib.h @@ -0,0 +1,115 @@ +// Commander X16 VERA (Versatile Embedded Retro Adapter) Video and Audio Processor +// https://github.com/commanderx16/x16-docs/blob/master/VERA%20Programmer's%20Reference.md + +// Author: Sven Van de Velde + +// --- VERA function encapsulation --- + +// --- VERA LAYERS --- + +// Set the configuration of the layer. +// - layer: Value of 0 or 1. +// - config: Specifies the modes which are specified using T256C / 'Bitmap Mode' / 'Color Depth'. +void vera_set_layer_config(unsigned byte layer, unsigned byte config); + +// Set the configuration of the layer. +// - layer: Value of 0 or 1. +// - config: Specifies the modes which are specified using T256C / 'Bitmap Mode' / 'Color Depth'. +unsigned byte vera_get_layer_config(unsigned byte layer); + +// Set the map width or height of the layer. +// - layer: Value of 0 or 1. +inline void vera_set_layer_map_width_32(unsigned byte layer); +inline void vera_set_layer_map_width_64(unsigned byte layer); +inline void vera_set_layer_map_width_128(unsigned byte layer); +inline void vera_set_layer_map_width_256(unsigned byte layer); +inline void vera_set_layer_map_height_32(unsigned byte layer); +inline void vera_set_layer_map_height_64(unsigned byte layer); +inline void vera_set_layer_map_height_128(unsigned byte layer); +inline void vera_set_layer_map_height_256(unsigned byte layer); + +// Enable the layer to be displayed on the screen. +// - layer: 0 or 1. +void vera_show_layer(unsigned byte layer); + +// Disable the layer to be displayed on the screen. +// - layer: 0 or 1. +void vera_hide_layer(unsigned byte layer); + +// Is the layer shown on the screen? +// - returns: 1 if layer is displayed on the screen, 0 if not. +unsigned byte vera_is_layer_shown(unsigned byte layer); + +// Set the base of the map for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - mapbase: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:9 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 512 bytes. +void vera_set_layer_mapbase(unsigned byte layer, unsigned byte mapbase); + +// Get the base of the map for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - return: Returns the base address of the tile map. +// Note that the register is a byte, specifying only bits 16:9 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 512 bytes! +unsigned byte vera_get_layer_mapbase(unsigned byte layer); + +// Set the base of the tiles for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - tilebase: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:11 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 2048 bytes! +void vera_set_layer_tilebase(unsigned byte layer, unsigned byte tilebase); + +// Get the base of the tiles for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - return: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:11 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 2048 bytes! +unsigned byte vera_get_layer_tilebase(unsigned byte layer); + + +// Set the front color for text output. The old front text color setting is returned. +// - layer: Value of 0 or 1. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_set_layer_textcolor(unsigned byte layer, unsigned byte color); + +// Get the front color for text output. The old front text color setting is returned. +// - layer: Value of 0 or 1. +// - return: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_textcolor(unsigned byte layer); + +// Set the back color for text output. The old back text color setting is returned. +// - layer: Value of 0 or 1. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_set_layer_backcolor(unsigned byte layer, unsigned byte color); + +// Get the back color for text output. The old back text color setting is returned. +// - layer: Value of 0 or 1. +// - return: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_backcolor(unsigned byte layer); + +// Get the text and back color for text output in 16 color mode. +// - layer: Value of 0 or 1. +// - return: an 8 bit value with bit 7:4 containing the back color and bit 3:0 containing the front color. +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_color(unsigned byte layer); + +// Scroll the horizontal (X) axis of the layer visible area over the layer tile map area. +// - layer: Value of 0 or 1. +// - scroll: A value between 0 and 4096. +inline void vera_set_layer_horizontal_scroll(byte layer, word scroll); + +// Scroll the vertical (Y) axis of the layer visible area over the layer tile map area. +// - layer: Value of 0 or 1. +// - scroll: A value between 0 and 4096. +inline void vera_set_layer_vertical_scroll(byte layer, word scroll); diff --git a/src/main/kc/lib/conio-cx16.c b/src/main/kc/lib/conio-cx16.c new file mode 100644 index 000000000..7f02b6e1f --- /dev/null +++ b/src/main/kc/lib/conio-cx16.c @@ -0,0 +1,373 @@ +// CX16 conio.h implementation +#include +#include + +// The screen width +#define CONIO_WIDTH conio_screen_width +// The screen height +#define CONIO_HEIGHT conio_screen_height +// The text screen base address, which is a 16:0 bit value in VERA VRAM. +// That is 128KB addressable space, thus 17 bits in total. +// CONIO_SCREEN_TEXT contains bits 15:0 of the address. +// CONIO_SCREEN_BANK contains bit 16, the the 64K memory bank in VERA VRAM (the upper 17th bit). +// !!! note that these values are not const for the cx16! +// This conio implements the two layers of VERA, which can be layer 0 or layer 1. +// Configuring conio to output to a different layer, will change these fields to the address base +// configured using VERA_L0_MAPBASE = 0x9f2e or VERA_L1_MAPBASE = 0x9f35. +// Using the function setscreenlayer(layer) will re-calculate using CONIO_SCREEN_TEXT and CONIO_SCREEN_BASE +// based on the values of VERA_L0_MAPBASE or VERA_L1_MAPBASE, mapping the base address of the selected layer. +// The function setscreenlayermapbase(layer,mapbase) allows to configure bit 16:9 of the +// mapbase address of the time map in VRAM of the selected layer VERA_L0_MAPBASE or VERA_L1_MAPBASE. +char* CONIO_SCREEN_TEXT = DEFAULT_SCREEN; +char CONIO_SCREEN_BANK = 0; // Default screen of the CX16 emulator uses memory bank 0 for text. +// The default text color +const char CONIO_TEXTCOLOR_DEFAULT = WHITE; +// The default back color +const char CONIO_BACKCOLOR_DEFAULT = BLUE; + +// Initializer for conio.h on X16 Commander. +#pragma constructor_for(conio_x16_init, cputc, clrscr, cscroll) + +// Set initial cursor position +void conio_x16_init() { + // Position cursor at current line + char * const BASIC_CURSOR_LINE = 0xD6; + char line = *BASIC_CURSOR_LINE; + screensize(&conio_screen_width, &conio_screen_height); + screenlayer(1); + vera_set_layer_textcolor(1, WHITE); + vera_set_layer_backcolor(1, BLUE); + vera_set_layer_mapbase(0,0x20); + vera_set_layer_mapbase(1,0x00); + if(line>=CONIO_HEIGHT) line=CONIO_HEIGHT-1; + gotoxy(0, line); +} + +// Return true if there's a key waiting, return false if not +unsigned char kbhit(void) { + + char ch = 0; + char* const chptr = &ch; + + char* const IN_DEV = $028A; // Current input device number + char* const GETIN = $FFE4; // CBM GETIN API + + kickasm(uses chptr, uses IN_DEV, uses GETIN) {{ + + jsr _kbhit + bne L3 + + jmp continue1 + + .var via1 = $9f60 //VIA#1 + .var d1pra = via1+1 + + _kbhit: + ldy d1pra // The count of keys pressed is stored in RAM bank 0. + stz d1pra // Set d1pra to zero to access RAM bank 0. + lda $A00A // Get number of characters from this address in the ROM of the CX16 (ROM 38). + sty d1pra // Set d1pra to previous value. + rts + + L3: + ldy IN_DEV // Save current input device + stz IN_DEV // Keyboard + phy + jsr GETIN // Read char, and return in .A + ply + sta chptr // Store the character read in ch + sty IN_DEV // Restore input device + ldx #>$0000 + rts + + continue1: + nop + }} + + return ch; +} + +// This requires the following constants to be defined +// - CONIO_WIDTH - The screen width +// - CONIO_HEIGHT - The screen height +// - CONIO_SCREEN_TEXT - The text screen address +// - CONIO_SCREEN_COLORS - The color screen address +// - CONIO_TEXTCOLOR_DEFAULT - The default text color + +#include + +// The number of bytes on the screen +#define CONIO_BYTES CONIO_HEIGHT*CONIO_WIDTH + +// The current cursor x-position +unsigned byte conio_cursor_x[2] = {0,0}; +// The current cursor y-position +unsigned byte conio_cursor_y[2] = {0,0}; +// The current text cursor line start +unsigned word conio_line_text[2] = {0x0000,0x0000}; +// Is a cursor whown when waiting for input (0: no, other: yes) +__ma unsigned byte conio_display_cursor = 0; +// Is scrolling enabled when outputting beyond the end of the screen (1: yes, 0: no). +// If disabled the cursor just moves back to (0,0) instead +unsigned byte conio_scroll_enable[2] = {1,1}; +// Variable holding the screen width; +__ma unsigned byte conio_screen_width = 0; +// Variable holding the screen height; +__ma unsigned byte conio_screen_height = 0; +// Variable holding the screen layer on the VERA card with which conio interacts; +__ma unsigned byte conio_screen_layer = 1; + +// Variables holding the current map width and map height of the layer. +__ma word conio_width = 0; +__ma word conio_height = 0; +__ma byte conio_skip = 0; + +// clears the screen and moves the cursor to the upper left-hand corner of the screen. +void clrscr(void) { + char* line_text = CONIO_SCREEN_TEXT; + word skip = (word)((word)1<ch; + *VERA_ADDRX_H = CONIO_SCREEN_BANK | VERA_INC_1; + for( char c=0;cCONIO_HEIGHT) y = 0; + if(x>=CONIO_WIDTH) x = 0; + conio_cursor_x[conio_screen_layer] = x; + conio_cursor_y[conio_screen_layer] = y; + unsigned int line_offset = (unsigned int)y << conio_skip; + conio_line_text[conio_screen_layer] = line_offset; +} + +// Return the current screen size. +void screensize(unsigned byte* x, unsigned byte* y) { + // VERA returns in VERA_DC_HSCALE the value of 128 when 80 columns is used in text mode, + // and the value of 64 when 40 columns is used in text mode. + // Basically, 40 columns mode in the VERA is a double scan mode. + // Same for the VERA_DC_VSCALE mode, but then the subdivision is 60 or 30 rows. + // I still need to test the other modes, but this will suffice for now for the pure text modes. + char hscale = (*VERA_DC_HSCALE) >> 7; + *x = 40 << hscale; + char vscale = (*VERA_DC_VSCALE) >> 7; + *y = 30 << vscale; + //printf("%u, %u\n", *x, *y); +} + +// Return the current screen size X width. +inline unsigned byte screensizex() { + return conio_screen_width; +} + +// Return the current screen size Y height. +inline unsigned byte screensizey() { + return conio_screen_height; +} + +// Return the X position of the cursor +inline unsigned byte wherex(void) { + return conio_cursor_x[conio_screen_layer]; +} + +// Return the Y position of the cursor +inline unsigned byte wherey(void) { + return conio_cursor_y[conio_screen_layer]; +} + +// Output one character at the current cursor position +// Moves the cursor forward. Scrolls the entire screen if needed +void cputc(char c) { + char color = vera_get_layer_color( conio_screen_layer); + char* conio_addr = CONIO_SCREEN_TEXT + conio_line_text[conio_screen_layer]; + + conio_addr += conio_cursor_x[conio_screen_layer] << 1; + if(c=='\n') { + cputln(); + } else { + // Select DATA0 + *VERA_CTRL &= ~VERA_ADDRSEL; + // Set address + *VERA_ADDRX_L = conio_addr; + *VERA_ADDRX_H = CONIO_SCREEN_BANK | VERA_INC_1; + *VERA_DATA0 = c; + *VERA_DATA0 = color; + + conio_cursor_x[conio_screen_layer]++; + byte scroll_enable = conio_scroll_enable[conio_screen_layer]; + if(scroll_enable) { + if(conio_cursor_x[conio_screen_layer] == CONIO_WIDTH) + cputln(); + } else { + if((unsigned int)conio_cursor_x[conio_screen_layer] == conio_width) + cputln(); + } + } +} + +// Print a newline +void cputln() { + // TODO: This needs to be optimized! other variations don't compile because of sections not available! + word temp = conio_line_text[conio_screen_layer]; + temp += (word)((word)1<addr; + *VERA_ADDRX_H = VERA_INC_1; + char color = vera_get_layer_color( conio_screen_layer); + for( unsigned int c=0;c0; i--) { + unsigned int line = (conio_cursor_y[conio_screen_layer] + i - 1) << conio_skip; + unsigned char* start = CONIO_SCREEN_TEXT + line; + memcpy_in_vram(0, start+((word)1<=CONIO_HEIGHT) { + if(conio_scroll_enable[conio_screen_layer]) { + insertup(); + gotoxy( 0, CONIO_HEIGHT-1); + } else { + if(conio_cursor_y[conio_screen_layer]>=conio_height) { + //gotoxy(0,0); + } + } + } +} + + +// Output a NUL-terminated string at the current cursor position +void cputs(const char* s) { + char c; + while(c=*s++) + cputc(c); +} + +// Move cursor and output one character +// Same as "gotoxy (x, y); cputc (c);" +void cputcxy(unsigned byte x, unsigned byte y, char c) { + gotoxy(x, y); + cputc(c); +} + +// Move cursor and output a NUL-terminated string +// Same as "gotoxy (x, y); puts (s);" +void cputsxy(unsigned byte x, unsigned byte y, const char* s) { + gotoxy(x, y); + cputs(s); +} + +// If onoff is 1, a cursor is displayed when waiting for keyboard input. +// If onoff is 0, the cursor is hidden when waiting for keyboard input. +// The function returns the old cursor setting. +unsigned byte cursor(unsigned byte onoff) { + char old = conio_display_cursor; + conio_display_cursor = onoff; + return old; +} + +// If onoff is 1, scrolling is enabled when outputting past the end of the screen +// If onoff is 0, scrolling is disabled and the cursor instead moves to (0,0) +// The function returns the old scroll setting. +unsigned byte scroll(unsigned byte onoff) { + char old = conio_scroll_enable[conio_screen_layer]; + conio_scroll_enable[conio_screen_layer] = onoff; + return old; +} + +// --- Defined in cx16.c and cx16-vera.h --- + +// --- layer management in VERA --- + +// Set the layer with which the conio will interact. +// - layer: value of 0 or 1. +void screenlayer(unsigned byte layer) { + layer &= $1; + conio_screen_layer = layer; + unsigned byte addr = vera_get_layer_mapbase(layer); + unsigned int addr_i = addr << 1; + CONIO_SCREEN_BANK = >addr_i; + CONIO_SCREEN_TEXT = addr_i << 8; + conio_width = vera_get_layer_map_width(conio_screen_layer); + conio_skip = (byte)(conio_width >> 4); + conio_height = vera_get_layer_map_height(conio_screen_layer); +} + + +// Set the front color for text output. The old front text color setting is returned. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +inline char textcolor(char color) { + return vera_set_layer_textcolor(conio_screen_layer, color); +} + +// Set the back color for text output. The old back text color setting is returned. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +inline char bgcolor(char color) { + return vera_set_layer_backcolor(conio_screen_layer, color); +} + +// Set the color for the border. The old color setting is returned. +char bordercolor(unsigned char color) { + // The border color register address + char old = *VERA_DC_BORDER; + *VERA_DC_BORDER = color; + return old; +} + diff --git a/src/main/kc/lib/conio.c b/src/main/kc/lib/conio.c index ef8c09ad1..c0e3c8823 100644 --- a/src/main/kc/lib/conio.c +++ b/src/main/kc/lib/conio.c @@ -17,6 +17,8 @@ #include "conio-nes.c" #elif defined(__ATARIXL__) #include "conio-atarixl.c" +#elif defined(__CX16__) +#include "conio-cx16.c" #else #error "Target platform does not support conio.h" #endif diff --git a/src/main/kc/lib/cx16.c b/src/main/kc/lib/cx16.c index 0fe122b36..16e00b984 100644 --- a/src/main/kc/lib/cx16.c +++ b/src/main/kc/lib/cx16.c @@ -54,3 +54,35 @@ void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num ) { for(char *s = src; s!=end; s++) *VERA_DATA0 = *s; } + +// Copy block of memory (from VRAM to VRAM) +// Copies the values from the location pointed by src to the location pointed by dest. +// The method uses the VERA access ports 0 and 1 to copy data from and to in VRAM. +// - src_bank: 64K VRAM bank number to copy from (0/1). +// - src: pointer to the location to copy from. Note that the address is a 16 bit value! +// - src_increment: the increment indicator, VERA needs this because addressing increment is automated by VERA at each access. +// - dest_bank: 64K VRAM bank number to copy to (0/1). +// - dest: pointer to the location to copy to. Note that the address is a 16 bit value! +// - dest_increment: the increment indicator, VERA needs this because addressing increment is automated by VERA at each access. +// - num: The number of bytes to copy +void memcpy_in_vram(char dest_bank, void *dest, char dest_increment, char src_bank, void *src, char src_increment, unsigned int num ) { + // Select DATA0 + *VERA_CTRL &= ~VERA_ADDRSEL; + // Set address + *VERA_ADDRX_L = src; + *VERA_ADDRX_H = src_increment | src_bank; + + // Select DATA1 + *VERA_CTRL |= VERA_ADDRSEL; + // Set address + *VERA_ADDRX_L = dest; + *VERA_ADDRX_H = dest_increment | dest_bank; + + // Transfer the data + for(unsigned int i=0; i +#include + +// --- VERA function encapsulation --- + +// --- VERA layer management --- +byte* vera_layer_config[2] = {VERA_L0_CONFIG, VERA_L1_CONFIG}; +byte vera_layer_enable[2] = { VERA_LAYER0_ENABLE, VERA_LAYER1_ENABLE }; + +byte* vera_layer_mapbase[2] = {VERA_L0_MAPBASE, VERA_L1_MAPBASE}; +byte* vera_layer_tilebase[2] = {VERA_L0_TILEBASE, VERA_L1_TILEBASE}; +byte* vera_layer_vscroll_l[2] = {VERA_L0_VSCROLL_L, VERA_L1_VSCROLL_L}; +byte* vera_layer_vscroll_h[2] = {VERA_L0_VSCROLL_H, VERA_L1_VSCROLL_H}; +byte* vera_layer_hscroll_l[2] = {VERA_L0_HSCROLL_L, VERA_L1_HSCROLL_L}; +byte* vera_layer_hscroll_h[2] = {VERA_L0_HSCROLL_H, VERA_L1_HSCROLL_H}; + +byte vera_layer_textcolor[2] = {WHITE, WHITE}; +byte vera_layer_backcolor[2] = {BLUE, BLUE}; + +// --- VERA addressing --- + +void vera_vram_address0(dword bankaddr, byte incr) { + word* word_l = &(bankaddr); + // Select DATA0 + *VERA_CTRL &= ~VERA_ADDRSEL; + // Set address + *VERA_ADDRX_L = <(*word_l); + *VERA_ADDRX_M = >(*word_l); + *VERA_ADDRX_H = <(*word_h) | incr; +} + +void vera_vram_address1(dword bankaddr, byte incr) { + word* word_l = &(bankaddr); + // Select DATA1 + *VERA_CTRL |= VERA_ADDRSEL; + // Set address + *VERA_ADDRX_L = <(*word_l); + *VERA_ADDRX_M = >(*word_l); + *VERA_ADDRX_H = <(*word_h) | incr; +} + +// --- VERA layer management --- + +// Set the configuration of the layer. +// - layer: Value of 0 or 1. +// - config: Specifies the modes which are specified using T256C / 'Bitmap Mode' / 'Color Depth'. +void vera_set_layer_config(char layer, char config) { + layer &= $1; + char* addr = vera_layer_config[layer]; + *addr = config; +} + +// Set the configuration of the layer. +// - layer: Value of 0 or 1. +// - config: Specifies the modes which are specified using T256C / 'Bitmap Mode' / 'Color Depth'. +char vera_get_layer_config(char layer) { + layer &= $1; + char* config = vera_layer_config[layer]; + return *config; +} + +// Set the map width or height of the layer. +// - layer: Value of 0 or 1. +inline void vera_set_layer_map_width_32(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_WIDTH_MASK; + *addr |= VERA_CONFIG_WIDTH_32; +} +inline void vera_set_layer_map_width_64(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + //*addr &= (~VERA_CONFIG_WIDTH_MASK) | VERA_CONFIG_WIDTH_64; + *addr &= ~VERA_CONFIG_WIDTH_MASK; + *addr |= VERA_CONFIG_WIDTH_64; +} +inline void vera_set_layer_map_width_128(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_WIDTH_MASK; + *addr |= VERA_CONFIG_WIDTH_128; +} +inline void vera_set_layer_map_width_256(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_WIDTH_MASK; + *addr |= VERA_CONFIG_WIDTH_256; +} +inline void vera_set_layer_map_height_32(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_HEIGHT_MASK; + *addr |= VERA_CONFIG_HEIGHT_32; +} +inline void vera_set_layer_map_height_64(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_HEIGHT_MASK; + *addr |= VERA_CONFIG_HEIGHT_64; +} +inline void vera_set_layer_map_height_128(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_HEIGHT_MASK; + *addr |= VERA_CONFIG_HEIGHT_128; +} +inline void vera_set_layer_map_height_256(unsigned byte layer) { + byte* addr = vera_layer_config[layer]; + *addr &= ~VERA_CONFIG_HEIGHT_MASK; + *addr |= VERA_CONFIG_HEIGHT_256; +} + +unsigned int const VERA_CONFIG_WIDTH[4] = { 32, 64, 128, 256 }; + +// Get the map width or height of the layer. +// - layer: Value of 0 or 1. +word vera_get_layer_map_width(unsigned byte layer) { + byte* config = vera_layer_config[layer]; + byte mask = (byte)VERA_CONFIG_WIDTH_MASK; + return VERA_CONFIG_WIDTH[ (*config & mask) >> 4]; +} + +unsigned int const VERA_CONFIG_HEIGHT[4] = { 32, 64, 128, 256 }; + +word vera_get_layer_map_height(unsigned byte layer) { + byte* config = vera_layer_config[layer]; + byte mask = VERA_CONFIG_HEIGHT_MASK; + return VERA_CONFIG_HEIGHT[ (*config & mask) >> 6]; +} + +// Enable the layer to be displayed on the screen. +// - layer: 0 or 1. +inline void vera_show_layer(char layer) { + *VERA_DC_VIDEO |= vera_layer_enable[layer]; +} + + +// Disable the layer to be displayed on the screen. +// - layer: 0 or 1. +inline void vera_hide_layer(char layer) { + *VERA_DC_VIDEO &= ~vera_layer_enable[layer]; +} + + +// Is the layer shown on the screen? +// - returns: 1 if layer is displayed on the screen, 0 if not. +char vera_is_layer_shown(char layer) { + layer &= $1; + return *VERA_DC_VIDEO & vera_layer_enable[layer]; +} + +// Set the base of the map layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - mapbase: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:9 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 512 bytes. +void vera_set_layer_mapbase(unsigned byte layer, unsigned byte mapbase) { + layer &= $1; + unsigned byte* addr = vera_layer_mapbase[layer]; + *addr = mapbase; +} + +// Get the base of the map layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - return: Returns the base address of the tile map. +// Note that the register is a byte, specifying only bits 16:9 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 512 bytes. +unsigned byte vera_get_layer_mapbase(unsigned byte layer) { + layer &= $1; + unsigned byte* mapbase = vera_layer_mapbase[layer]; + return *mapbase; +} + +// Set the base of the tiles for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - tilebase: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:11 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 2048 bytes! +void vera_set_layer_tilebase(unsigned byte layer, unsigned byte tilebase) { + layer &= $1; + unsigned byte* addr = vera_layer_tilebase[layer]; + *addr = tilebase; +} + +// Get the base of the tiles for the layer with which the conio will interact. +// - layer: Value of 0 or 1. +// - return: Specifies the base address of the tile map. +// Note that the register only specifies bits 16:11 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 2048 bytes! +unsigned byte vera_get_layer_tilebase(unsigned byte layer) { + layer &= $1; + unsigned byte* tilebase = vera_layer_tilebase[layer]; + return *tilebase; +} + +// Get the tile base address of the tiles for the layer. +// - layer: Value of 0 or 1. +// - return: Specifies the base address of the tile map, which is calculated as an unsigned long int. +// Note that the register only specifies bits 16:11 of the address, +// so the resulting address in the VERA VRAM is always aligned to a multiple of 2048 bytes! +dword vera_get_layer_tilebase_address(byte layer) { + layer &= $1; + byte tilebase = *vera_layer_tilebase[layer]; + dword address = tilebase; + address &= $FC; + address <<= 8; + address <<= 1; + return address; +} + +// --- VERA color management --- + +// Set the front color for text output. The old front text color setting is returned. +// - layer: Value of 0 or 1. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_set_layer_textcolor(unsigned byte layer, unsigned byte color) { + layer &= $1; + unsigned byte old = vera_layer_textcolor[layer]; + vera_layer_textcolor[layer] = color; + return old; +} + +// Get the front color for text output. The old front text color setting is returned. +// - layer: Value of 0 or 1. +// - return: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_textcolor(unsigned byte layer) { + layer &= $1; + return vera_layer_textcolor[layer]; +} + +// Set the back color for text output. The old back text color setting is returned. +// - layer: Value of 0 or 1. +// - color: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_set_layer_backcolor(unsigned byte layer, unsigned byte color) { + layer &= $1; + unsigned byte old = vera_layer_backcolor[layer]; + vera_layer_backcolor[layer] = color; + return old; +} + +// Get the back color for text output. The old back text color setting is returned. +// - layer: Value of 0 or 1. +// - return: a 4 bit value ( decimal between 0 and 15). +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_backcolor(unsigned byte layer) { + layer &= $1; + return vera_layer_backcolor[layer]; +} + +// Get the text and back color for text output in 16 color mode. +// - layer: Value of 0 or 1. +// - return: an 8 bit value with bit 7:4 containing the back color and bit 3:0 containing the front color. +// This will only work when the VERA is in 16 color mode! +// Note that on the VERA, the transparent color has value 0. +unsigned byte vera_get_layer_color(unsigned byte layer) { + layer &= $1; + return ((vera_layer_backcolor[layer] << 4) | vera_layer_textcolor[layer]); +} + + +// Scroll the horizontal (X) axis of the layer visible area over the layer tile map area. +// - layer: Value of 0 or 1. +// - scroll: A value between 0 and 4096. +inline void vera_set_layer_horizontal_scroll(byte layer, word scroll) { + *vera_layer_hscroll_l[layer] = scroll; +} + +// Scroll the vertical (Y) axis of the layer visible area over the layer tile map area. +// - layer: Value of 0 or 1. +// - scroll: A value between 0 and 4096. +inline void vera_set_layer_vertical_scroll(byte layer, word scroll) { + *vera_layer_vscroll_l[layer] = scroll; +} diff --git a/src/main/kc/target/cx16.tgt b/src/main/kc/target/cx16.tgt index db826e32a..031034ab1 100644 --- a/src/main/kc/target/cx16.tgt +++ b/src/main/kc/target/cx16.tgt @@ -5,7 +5,7 @@ "start_address": "0x080d", "cpu": "WDC65C02", "interrupt": "rom_min_cx16", - "emulator": "x16emu -debug -run -scale 2 -prg", + "emulator": "x16emu -debug -run -prg", "defines": { "__CX16__": 1 } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index b539e10b1..30ce14fc2 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -458,6 +458,17 @@ public class TestPrograms { compileAndCompare("examples/nes/nes-demo.c"); } + @Test + public void testCx16VeraLayers() throws IOException, URISyntaxException { + compileAndCompare("examples/cx16/veralayers.c"); + } + + @Test + public void testCx16TileMap() throws IOException, URISyntaxException { + compileAndCompare("examples/cx16/tilemap.c"); + } + + @Test public void testCx16Sprites() throws IOException, URISyntaxException { compileAndCompare("examples/cx16/sprites.c"); diff --git a/src/test/kc/examples/cx16/sprites.c b/src/test/kc/examples/cx16/sprites.c index 682e741e1..794fe121b 100644 --- a/src/test/kc/examples/cx16/sprites.c +++ b/src/test/kc/examples/cx16/sprites.c @@ -92,7 +92,7 @@ volatile unsigned int sin_idx_x = 119; volatile unsigned int sin_idx_y = 79; // VSYNC Interrupt Routine -__interrupt(rom_sys_cx16) void irq_vsync() { +__interrupt void irq_vsync() { // Move the sprite around if(++sin_idx_x==SINX_LEN) sin_idx_x = 0; if(--sin_idx_y==0xffff) sin_idx_y = SINY_LEN-1; @@ -112,9 +112,4 @@ __interrupt(rom_sys_cx16) void irq_vsync() { // Reset the VSYNC interrupt *VERA_ISR = VERA_VSYNC; - // Exit CX16 KERNAL IRQ - asm { - // soft exit (keep kernal running) - jmp $e034 - } -} +} diff --git a/src/test/kc/examples/cx16/tilemap.c b/src/test/kc/examples/cx16/tilemap.c new file mode 100644 index 000000000..17b1ed884 --- /dev/null +++ b/src/test/kc/examples/cx16/tilemap.c @@ -0,0 +1,149 @@ +// Example program for the Commander X16. +// Demonstrates the usage of the VERA layer 0 and 1. + +// Author: Sven Van de Velde + +// The default layer of the CX16 is layer 1. +// The CX16 starts in tile map mode, 1BPP in 16 color mode, and uses 8x8 tiles. +// The map base is address 0x00000 in VERA VRAM, the tile map is address 0x0F800. + +#pragma target(cx16) +#include +#include +#include +#include <6502.h> + +void main() { + + textcolor(WHITE); + bgcolor(BLACK); + clrscr(); + + // Now we set the tile map width and height. + vera_set_layer_mapbase(0,0x80); // Set the map base to address 0x10000 in VERA VRAM! + vera_set_layer_config(0, vera_get_layer_config(1)); + vera_set_layer_tilebase(0, vera_get_layer_tilebase(1)); + vera_set_layer_map_width_128(0); + vera_set_layer_map_height_128(0); + dword tilebase = vera_get_layer_tilebase_address(0); + + screenlayer(0); + scroll(0); // Scrolling on conio is deactivated, so conio will output beyond the borders of the visible screen. + textcolor(WHITE); + bgcolor(GREEN); + + draw_characters(tilebase); + + // Enable VSYNC IRQ (also set line bit 8 to 0) + SEI(); + *KERNEL_IRQ = &irq_vsync; + *VERA_IEN = VERA_VSYNC; + CLI(); + + vera_show_layer(0); + while(!kbhit()); + + vera_hide_layer(0); + textcolor(GREY); + bgcolor(GREEN); + draw_characters(tilebase); + vera_show_layer(0); + + screenlayer(1); + + textcolor(WHITE); + bgcolor(BLACK); + printf("\n\nthis demo displays the design of the standard x16 commander\n"); + printf("character set on the vera layer 0. it's the character set i grew up with :-).\n"); + printf("\nthe smooth scrolling is implemented by manipulating the scrolling \n"); + printf("registers of layer 0. at each raster line interrupt, \n"); + printf("the x and y scrolling registers are manipulated. the cx16 terminal \n"); + printf("works on layer 1. when layer 0 is enabled with the scrolling, \n"); + printf("it gives a nice background effect. this technique can be used to implement\n"); + printf("smooth scrolling backgrounds using tile layouts in games or demos.\n"); + + textcolor(YELLOW); + printf("\npress a key to continue ..."); + + while(!kbhit()); + + screenlayer(0); + vera_hide_layer(0); + textcolor(DARK_GREY); + bgcolor(BLACK); + draw_characters(tilebase); + vera_show_layer(0); + + screenlayer(1); + gotoxy(0,20); + +} + +void draw_characters(dword tilebase) { + dword tilecolumn = tilebase; + dword tilerow = tilebase; + clrscr(); + + for(byte y:0..15) { + tilerow = tilebase; + for(byte r:0..7) { + tilecolumn = tilerow; + for(byte x:0..15) { + vera_vram_address0(tilecolumn,VERA_INC_0); + byte data = *VERA_DATA0; + byte bit = data; + for(byte b:8..1) { + bit = (data >> (b-1)) & $1; + printf("%c", (char)((bit)?'*':'.')); + } + tilecolumn += 8; + printf(""); + } + //printf("\n"); + tilerow += 1; + } + tilebase += 8*16; + } +} + +// X sine index +volatile int scroll_x = 0; +volatile int scroll_y = 0; +volatile int delta_x = 2; +volatile int delta_y = 0; +volatile int speed = 2; + +// VSYNC Interrupt Routine +__interrupt void irq_vsync() { + + + scroll_x += delta_x; + scroll_y += delta_y; + + if( scroll_x>(128*8-80*8)) { + delta_x = 0; + delta_y = speed; + scroll_x = (128*8-80*8); + } + if( scroll_y>(128*8-60*8)) { + delta_x = -speed; + delta_y = 0; + scroll_y = (128*8-60*8); + } + if(scroll_x<0) { + delta_x = 0; + delta_y = -speed; + scroll_x = 0; + } + if(scroll_y<0) { + delta_x = speed; + delta_y = 0; + scroll_y = 0; + } + + vera_set_layer_horizontal_scroll(0,(word)scroll_x); + vera_set_layer_vertical_scroll(0,(word)scroll_y); + + // Reset the VSYNC interrupt + *VERA_ISR = VERA_VSYNC; +} \ No newline at end of file diff --git a/src/test/kc/examples/cx16/veralayers.c b/src/test/kc/examples/cx16/veralayers.c new file mode 100644 index 000000000..669bb96c7 --- /dev/null +++ b/src/test/kc/examples/cx16/veralayers.c @@ -0,0 +1,134 @@ +// Example program for the Commander X16. +// Demonstrates the usage of the VERA layer 0 and 1. + +// Author: Sven Van de Velde + +// The default layer of the CX16 is layer 1. +// The CX16 starts in tile map mode, 1BPP in 16 color mode, and uses 8x8 tiles. +// The map base is address 0x00000 in VERA VRAM, the tile map is address 0x0F800. + +#pragma target(cx16) +#include +#include +#include + +void main() { + + textcolor(WHITE); + bgcolor(BLACK); + clrscr(); + + // Wait for a keypress and after clear the line! + textcolor(YELLOW); + printf("press a key"); + while(!kbhit()); + clearline(); + + screenlayer(1); + + gotoxy(0,16); + textcolor(GREEN); + + printf("this program demonstrates the layer functionality in text mode.\n"); + + // Here we use the screensizex and screensizey functions to show the width and height of the text screen. + printf("\nvera card width = %u; height = %u\n", screensizex(), screensizey()); + + // This is the content of the main controller registers of the VERA of layer 1. + // Layer 1 is the default layer that is activated in the CX16 at startup. + // It displays the characters in 1BPP 16x16 color mode! + unsigned byte dcvideo = *VERA_DC_VIDEO; + printf("\nvera dc video = %x\n", dcvideo); + unsigned byte config = vera_get_layer_config(1); + printf("\nvera layer 1 config = %x\n", config); + unsigned byte layershown = vera_is_layer_shown(1); + printf("vera layer 1 shown = %c\n", layershown); + unsigned byte mapbase = vera_get_layer_mapbase(1); + unsigned byte tilebase = vera_get_layer_tilebase(1); + printf("vera layer 1 mapbase = %hhx, tilebase = %hhx\n", mapbase, tilebase); + + // Wait for a keypress and after clear the line! + textcolor(YELLOW); + printf("press a key"); + while(!kbhit()); + clearline(); + + // Now we continue with demonstrating the layering! + // We set the mapbase of layer 0 to an address in VRAM. + // We copy the tilebase address from layer 1, so that we reference to the same tilebase. + // We print a text on layer 0, which of course, won't yet be displayed, + // because we haven't activated layer 0 on the VERA. + // But the text will be printed and awaiting to be displayer later, once we activate layer 0! + // But first, we also print the layer 0 VERA configuration. + // This statement sets the base of the display layer 1 at VRAM address 0x0200 + + vera_set_layer_mapbase(0,0x80); // Set the map base to address 0x10000 in VERA VRAM! + vera_set_layer_config(0, vera_get_layer_config(1)); + vera_set_layer_tilebase(0, vera_get_layer_tilebase(1)); + + textcolor(WHITE); + config = vera_get_layer_config(0); + printf("\nvera layer 0 config = %x\n", vera_get_layer_config(0)); + layershown = vera_is_layer_shown(0); + printf("vera layer 0 shown = %x\n", layershown); + mapbase = vera_get_layer_mapbase(0); + tilebase = vera_get_layer_tilebase(0); + printf("vera layer 0 mapbase = %x, tilebase = %x\n", mapbase, tilebase); + + // Now we print the layer 0 text on the layer 0! + screenlayer(0); // We set conio to output to layer 0 instead of layer 1! + textcolor(BLUE); + bgcolor(BLACK); + clrscr(); // We clear the screen of layer 0! + bgcolor(WHITE); + gotoxy(19,4); + printf(" "); + gotoxy(19,5); + printf(" this is printed on layer 0 !!! "); + gotoxy(19,6); + printf(" "); + + screenlayer(1); // Now we ask conio again to output to layer 1! + + // Wait for a keypress and after clear the line! + textcolor(YELLOW); + bgcolor(BLACK); + printf("press a key to show layer 0 and show the text!"); + while(!kbhit()); + clearline(); + + // Now we activate layer 0. + vera_show_layer(0); + textcolor(WHITE); + bgcolor(BLACK); + printf("vera layer 0 shown = %x. ", vera_is_layer_shown(0)); + + // Wait for a keypress and after clear the line! + textcolor(YELLOW); + bgcolor(BLACK); + printf("press a key to hide layer 0 and hide the text again"); + while(!kbhit()); + clearline(); + + vera_hide_layer(0); + textcolor(WHITE); + bgcolor(BLACK); + printf("vera layer 0 shown = %x. ", vera_is_layer_shown(0)); + + // Wait for a keypress and after clear the line! + textcolor(YELLOW); + bgcolor(BLACK); + printf("press a key to finish"); + while(!kbhit()); + clearline(); + + clrscr(); + textcolor(RED); + bgcolor(WHITE); + gotoxy(19,10); + printf(" "); + gotoxy(19,11); + printf(" analyze the code and learn! "); + gotoxy(19,12); + printf(" "); +}