diff --git a/.gitignore b/.gitignore index 47ba5647f..35411a4a6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ */bin/ */workspace.xml ./target/ +target/ **/.DS_Store +.project diff --git a/src/main/fragment/mos6502-common/_deref_(_deref_qbuc1)=_deref_(_deref_qbuc1)_bxor_vbuc2.asm b/src/main/fragment/mos6502-common/_deref_(_deref_qbuc1)=_deref_(_deref_qbuc1)_bxor_vbuc2.asm new file mode 100644 index 000000000..c41b463f3 --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_(_deref_qbuc1)=_deref_(_deref_qbuc1)_bxor_vbuc2.asm @@ -0,0 +1,8 @@ +ldy {c1} +sty $fe +ldy {c1}+1 +sty $ff +ldy #0 +lda ($fe),y +eor #{c2} +sta ($fe),y \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/_deref_(deref_qbuz1)=vbuaa.asm b/src/main/fragment/mos6502-common/_deref_(deref_qbuz1)=vbuaa.asm new file mode 100644 index 000000000..ae531e3d7 --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_(deref_qbuz1)=vbuaa.asm @@ -0,0 +1,3 @@ +lda {z1} +ldy #0 +sta ({z2}),y \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/_deref_pwuc1_eq_vbuc2_then_la1.asm b/src/main/fragment/mos6502-common/_deref_pwuc1_eq_vbuc2_then_la1.asm new file mode 100644 index 000000000..61aac520f --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pwuc1_eq_vbuc2_then_la1.asm @@ -0,0 +1,8 @@ +ldy #1 +lda ({c1}),y +bne !+ +dey +lda ({c1}),y +cmp #{c2} +beq {la1} +!: diff --git a/src/main/fragment/mos6502-common/_deref_pwuc1_neq_vbuc2_then_la1.asm b/src/main/fragment/mos6502-common/_deref_pwuc1_neq_vbuc2_then_la1.asm new file mode 100644 index 000000000..39af8fb0d --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pwuc1_neq_vbuc2_then_la1.asm @@ -0,0 +1,7 @@ +ldy #1 +lda ({c1}),y +bne {la1} +dey +lda ({c1}),y +cmp #{c2} +bne {la1} diff --git a/src/main/fragment/mos6502-common/vbuaa=_deref_(_deref_qbuc1)_bxor_vbuc2.asm b/src/main/fragment/mos6502-common/vbuaa=_deref_(_deref_qbuc1)_bxor_vbuc2.asm new file mode 100644 index 000000000..43b8fbf89 --- /dev/null +++ b/src/main/fragment/mos6502-common/vbuaa=_deref_(_deref_qbuc1)_bxor_vbuc2.asm @@ -0,0 +1,7 @@ +ldy {c1} +sty $fe +ldy {c1}+1 +sty $ff +ldy #0 +lda ($fe),y +eor #{c2} diff --git a/src/main/fragment/mos6502-common/vbuaa=_deref_pwuc1_band_vbuc2.asm b/src/main/fragment/mos6502-common/vbuaa=_deref_pwuc1_band_vbuc2.asm new file mode 100644 index 000000000..bbcc56d74 --- /dev/null +++ b/src/main/fragment/mos6502-common/vbuaa=_deref_pwuc1_band_vbuc2.asm @@ -0,0 +1,2 @@ +lda {c1} +and #{c2} \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vbuz1=_deref_(_deref_qbuc1)_bxor_vbuc2.asm b/src/main/fragment/mos6502-common/vbuz1=_deref_(_deref_qbuc1)_bxor_vbuc2.asm new file mode 100644 index 000000000..353b52e9c --- /dev/null +++ b/src/main/fragment/mos6502-common/vbuz1=_deref_(_deref_qbuc1)_bxor_vbuc2.asm @@ -0,0 +1,8 @@ +ldy {c1} +sty $fe +ldy {c1}+1 +sty $ff +ldy #0 +lda ($fe),y +eor #{c2} +sta {z1} \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vbuz1=_deref_pwuc1_band_vbuc2.asm b/src/main/fragment/mos6502-common/vbuz1=_deref_pwuc1_band_vbuc2.asm new file mode 100644 index 000000000..d2ab70bf4 --- /dev/null +++ b/src/main/fragment/mos6502-common/vbuz1=_deref_pwuc1_band_vbuc2.asm @@ -0,0 +1,3 @@ +lda {c1} +and #{c2} +sta {z1} diff --git a/src/main/kc/include/atari-xl.h b/src/main/kc/include/atari-xl.h index 29bf0e6b3..2e0ce83d0 100644 --- a/src/main/kc/include/atari-xl.h +++ b/src/main/kc/include/atari-xl.h @@ -5,6 +5,30 @@ #include #include +// Atari ZP registers + +// 1-byte cursor row +char * ROWCRS = 0x54; + +// 2-byte cursor column +word * COLCRS = 0x55; + +// 2-byte saved memory scan counter +char ** const SAVMSC = 0x58; + +// data under cursor +char * const OLDCHR = 0x5D; + +// 2-byte saved cursor memory address +char ** const OLDADR = 0x5E; + +// Cursor inhibit flag, 0 turns on, any other number turns off. Cursor doesn't change until it moves next. +char * const CRSINH = 0x2F0; + +// Internal hardware value for the last key pressed. Set to 0xFF to clear. +char * const CH = 0x2FC; + + // Atari GTIA write registers struct ATARI_GTIA_WRITE * const GTIA = 0xd000; @@ -40,3 +64,38 @@ char * LPENH = 0x234; // OS Shadow ANTIC Light Pen Vertical Position ($D40D) char * LPENV = 0x235; +// Color register zero, color of playfield zero. Shadow for 53270 ($D016) +char * const COLOR0 = 0x2C4; + +// Shadow for 53271 ($D017). Text color in Gr.0 +char * const COLOR1 = 0x2C5; + +// Shadow for 53272 ($D018). Background color in GR.0 +char * const COLOR2 = 0x2C6; + +// Shadow for 53273 ($D019) +char * const COLOR3 = 0x2C7; + +// Shadow for 53274 ($D01A). Border color in GR.0 +char * const COLOR4 = 0x2C8; + +// Atari colours - names from Mapping the Atari. +// Add luminance values 0-14 (even only) to increase brightness +const char BLACK = 0x00; +const char RUST = 0x10; +const char RED_ORANGE = 0x20; +const char DARK_ORANGE = 0x30; +const char RED = 0x40; +const char DARK_LAVENDER = 0x50; +const char COBALT_BLUE = 0x60; +const char ULTRAMARINE = 0x70; +const char MEDIUM_BLUE = 0x80; +const char DARK_BLUE = 0x90; +const char BLUE_GREY = 0xA0; +const char OLIVE_GREEN = 0xB0; +const char MEDIUM_GREEN = 0xC0; +const char DARK_GREEN = 0xD0; +const char ORANGE_GREEN = 0xE0; +const char ORANGE = 0xF0; + +const char WHITE = 0xFE; diff --git a/src/main/kc/lib/conio-atarixl.c b/src/main/kc/lib/conio-atarixl.c new file mode 100644 index 000000000..26405711a --- /dev/null +++ b/src/main/kc/lib/conio-atarixl.c @@ -0,0 +1,239 @@ +// Atari XL conio.h implementation +#include +#include +#include + +// The screen width +#define CONIO_WIDTH 40 +// The screen height +#define CONIO_HEIGHT 24 + +// The current reverse value indicator. Values 0 or 0x80 for reverse text +__ma char conio_reverse_value = 0; + +// The current cursor enable flag. 1 = on, 0 = off. +__ma char conio_display_cursor = 1; + +// The current scroll enable flag. 1 = on, 0 = off. +__ma char conio_scroll_enable = 1; + +// Move cursor and output one character +// Same as "gotoxy (x, y); cputc (c);" +void cputcxy(unsigned char x, unsigned char y, char c) { + gotoxy(x, y); + cputc(c); +} + +// Output one character at the current cursor position +// Moves the cursor forward. Scrolls the entire screen if needed +void cputc(char c) { + char screenCode; + if (c == '\r') { // 0x0d, CR = just set the cursor x value to 0 + *COLCRS = 0; + setcursor(); + } else if(c == '\n' || c == 0x9b) { // 0x0a LF, or atascii EOL + *COLCRS = 0; + newline(); + } else { + putchar(convertToScreenCode(&c)); + (*COLCRS)++; + if (*COLCRS == CONIO_WIDTH) { + *COLCRS = 0; + newline(); + } else { + setcursor(); + } + } +} + +// Puts a character to the screen a the current location. Uses internal screencode. Deals with storing the old cursor value +void putchar(unsigned char code) { + **OLDADR = *OLDCHR; + char * loc = cursorLocation(); + char newChar = code | conio_reverse_value; + *loc = newChar; + *OLDCHR = newChar; + setcursor(); +} + +// 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 a NUL-terminated string +// Same as "gotoxy (x, y); puts (s);" +void cputsxy(unsigned char x, unsigned char y, const char* s) { + gotoxy(x, y); + cputs(s); +} + +// Return a pointer to the location of the cursor +char * cursorLocation() { + return *SAVMSC + (word)(*ROWCRS)*CONIO_WIDTH + *COLCRS; +} + +void newline() { + if ((*ROWCRS)++ == CONIO_HEIGHT) { + if (conio_scroll_enable == 1) { + // first hide the current screen cursor, so it doesn't scroll, but only if it is on + if (conio_display_cursor == 1) { + **OLDADR ^= 0x80; + } + // move screen up 1 line + char * start = *SAVMSC; + memcpy(start, start + CONIO_WIDTH, CONIO_WIDTH * 23); + memset(start + CONIO_WIDTH * 23, 0x00, CONIO_WIDTH); + *ROWCRS = CONIO_HEIGHT - 1; + } else { + gotoxy(0, 0); + } + } + setcursor(); +} + +// Handles cursor movement, displaying it if required, and inverting character it is over if there is one (and enabled) +void setcursor() { + // save the current oldchr into oldadr + **OLDADR = *OLDCHR; + // work out the new location for oldadr based on new column/row + char * loc = cursorLocation(); + char c = *loc; + *OLDCHR = c; + *OLDADR = loc; + if (conio_display_cursor == 0) { + // cursor is off, don't affect the character at all, but do turn off cursor + *CRSINH = 1; + } else { + // cursor is on, so invert the inverse bit and turn cursor on + *CRSINH = 0; + c = c ^ 0x80; + } + **OLDADR = c; +} + +// Print a newline +void cputln() { + *COLCRS = 0; + newline(); +} + +// Set the cursor to the specified position +void gotoxy(unsigned char x, unsigned char y) { + *COLCRS = x; + *ROWCRS = y; + setcursor(); +} + +// Sets reverse mode for text. 1 enables reverse, 0 disables. Returns the old value. +unsigned char revers(unsigned char onoff) { + char old = conio_reverse_value; + if (onoff == 0) conio_reverse_value = 0; else conio_reverse_value = 0x80; + 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 char scroll(unsigned char onoff) { + char old = conio_scroll_enable; + conio_scroll_enable = onoff; + return old; +} + +// clears the screen and moves the cursor to the upper left-hand corner of the screen. +void clrscr() { + // Fill entire screen with spaces + memset(*SAVMSC, 0x00, CONIO_WIDTH * CONIO_HEIGHT); // 0x00 is screencode for space character + // set the old character to a space so the cursor doesn't reappear at the last position it was at + *OLDCHR = 0x00; + gotoxy(0,0); +} + +// If onoff is 1, a cursor is displayed when any text is output. +// If onoff is 0, the cursor is hidden instead. +unsigned char cursor(unsigned char onoff) { + // this just updates internal cursor flag value, doesn't update CRSINH + // onoff: 0 => cursor off, 1 => cursor on + // CRSINH is opposite to this, 0 == ON, 1 == OFF + char oldValue = conio_display_cursor; + conio_display_cursor = onoff; + return oldValue; +} + +// Return the X position of the cursor +unsigned char wherex() { + return (*COLCRS & 0xff); +} + +// Return the Y position of the cursor +unsigned char wherey() { + return *ROWCRS; +} + +// Return the current screen size. +void screensize(unsigned char *x, unsigned char *y) { + *x = CONIO_WIDTH; + *y = CONIO_HEIGHT; +} + +// Return the current screen size X width. +char screensizex() { + return CONIO_WIDTH; +} + +// Return the current screen size Y height. +char screensizey() { + return CONIO_HEIGHT; +} + +// Return 1 if there's a key waiting, return 0 if not +unsigned char kbhit() { + if (*CH == 0xff) return 0; else return 1; +} + +// Clears the key waiting buffer. +inline void clrkb() { + *CH = 0xff; +} + +// Set the color for the text. The old color setting is returned. +unsigned char textcolor(unsigned char color) { + char old = *COLOR1; + *COLOR1 = color; + return old; +} + +// Set the color for the background. The old color setting is returned. +unsigned char bgcolor(unsigned char color) { + char old = *COLOR2; + *COLOR2 = color; + return old; +} + +// Set the color for the border. The old color setting is returned. +unsigned char bordercolor(unsigned char color) { + char old = *COLOR4; + *COLOR4 = color; + return old; +} + +// Convert an atascii character to its screen code representation. Requires 1 page lookup table generated below. +inline unsigned char convertToScreenCode(unsigned char* v) { + return rawmap[*v]; +} + +// create a static table to map char value to screen value +// use KickAsm functions to create a table of code -> screen code values, using cc65 algorithm +char rawmap[0x100] = kickasm {{ + .var ht = Hashtable().put(0,64, 1,0, 2,32, 3,96) // the table for converting bit 6,7 into ora value + .for(var i=0; i<256; i++) { + .var idx = (i & $60) / 32 + .var mask = i & $9f + .byte mask | ht.get(idx) + } +}}; + diff --git a/src/main/kc/lib/conio-cbm-shared.c b/src/main/kc/lib/conio-cbm-shared.c index 71537ddf8..9b74bd8b3 100644 --- a/src/main/kc/lib/conio-cbm-shared.c +++ b/src/main/kc/lib/conio-cbm-shared.c @@ -160,7 +160,7 @@ unsigned char cursor(unsigned char onoff) { } // If onoff is 1, scrolling is enabled when outputting past the end of the screen -// If onoff is 1, scrolling is disabled and the cursor instead moves to (0,0) +// If onoff is 0, scrolling is disabled and the cursor instead moves to (0,0) // The function returns the old scroll setting. unsigned char scroll(unsigned char onoff) { char old = conio_scroll_enable; diff --git a/src/main/kc/lib/conio.c b/src/main/kc/lib/conio.c index d151c7a5f..ef8c09ad1 100644 --- a/src/main/kc/lib/conio.c +++ b/src/main/kc/lib/conio.c @@ -15,6 +15,8 @@ #include "conio-mega65.c" #elif defined(__NES__) #include "conio-nes.c" +#elif defined(__ATARIXL__) +#include "conio-atarixl.c" #else #error "Target platform does not support conio.h" #endif