diff --git a/cbm_ascii_charmap.h b/cbm_ascii_charmap.h new file mode 100644 index 0000000..f1381ab --- /dev/null +++ b/cbm_ascii_charmap.h @@ -0,0 +1,262 @@ +// modified CC65 charmap to allow pure ASCII on VIC20 + +#pragma warn (remap-zero, push, off) + +#pragma charmap (0x00, 0x00) +#pragma charmap (0x01, 0x01) +#pragma charmap (0x02, 0x02) +#pragma charmap (0x03, 0x03) +#pragma charmap (0x04, 0x04) +#pragma charmap (0x05, 0x05) +#pragma charmap (0x06, 0x06) +#pragma charmap (0x07, 0x07) +#pragma charmap (0x08, 0x08) +#pragma charmap (0x09, 0x09) +#pragma charmap (0x0A, 0x0A) +#pragma charmap (0x0B, 0x0B) +#pragma charmap (0x0C, 0x0C) +#pragma charmap (0x0D, 0x0D) +#pragma charmap (0x0E, 0x0E) +#pragma charmap (0x0F, 0x0F) +#pragma charmap (0x10, 0x10) +#pragma charmap (0x11, 0x11) +#pragma charmap (0x12, 0x12) +#pragma charmap (0x13, 0x13) +#pragma charmap (0x14, 0x14) +#pragma charmap (0x15, 0x15) +#pragma charmap (0x16, 0x16) +#pragma charmap (0x17, 0x17) +#pragma charmap (0x18, 0x18) +#pragma charmap (0x19, 0x19) +#pragma charmap (0x1A, 0x1A) +#pragma charmap (0x1B, 0x1B) +#pragma charmap (0x1C, 0x1C) +#pragma charmap (0x1D, 0x1D) +#pragma charmap (0x1E, 0x1E) +#pragma charmap (0x1F, 0x1F) +#pragma charmap (0x20, 0x20) +#pragma charmap (0x21, 0x21) +#pragma charmap (0x22, 0x22) +#pragma charmap (0x23, 0x23) +#pragma charmap (0x24, 0x24) +#pragma charmap (0x25, 0x25) +#pragma charmap (0x26, 0x26) +#pragma charmap (0x27, 0x27) +#pragma charmap (0x28, 0x28) +#pragma charmap (0x29, 0x29) +#pragma charmap (0x2A, 0x2A) +#pragma charmap (0x2B, 0x2B) +#pragma charmap (0x2C, 0x2C) +#pragma charmap (0x2D, 0x2D) +#pragma charmap (0x2E, 0x2E) +#pragma charmap (0x2F, 0x2F) +#pragma charmap (0x30, 0x30) +#pragma charmap (0x31, 0x31) +#pragma charmap (0x32, 0x32) +#pragma charmap (0x33, 0x33) +#pragma charmap (0x34, 0x34) +#pragma charmap (0x35, 0x35) +#pragma charmap (0x36, 0x36) +#pragma charmap (0x37, 0x37) +#pragma charmap (0x38, 0x38) +#pragma charmap (0x39, 0x39) +#pragma charmap (0x3A, 0x3A) +#pragma charmap (0x3B, 0x3B) +#pragma charmap (0x3C, 0x3C) +#pragma charmap (0x3D, 0x3D) +#pragma charmap (0x3E, 0x3E) +#pragma charmap (0x3F, 0x3F) +#pragma charmap (0x40, 0x40) +#pragma charmap (0x41, 0x41) +#pragma charmap (0x42, 0x42) +#pragma charmap (0x43, 0x43) +#pragma charmap (0x44, 0x44) +#pragma charmap (0x45, 0x45) +#pragma charmap (0x46, 0x46) +#pragma charmap (0x47, 0x47) +#pragma charmap (0x48, 0x48) +#pragma charmap (0x49, 0x49) +#pragma charmap (0x4A, 0x4A) +#pragma charmap (0x4B, 0x4B) +#pragma charmap (0x4C, 0x4C) +#pragma charmap (0x4D, 0x4D) +#pragma charmap (0x4E, 0x4E) +#pragma charmap (0x4F, 0x4F) +#pragma charmap (0x50, 0x50) +#pragma charmap (0x51, 0x51) +#pragma charmap (0x52, 0x52) +#pragma charmap (0x53, 0x53) +#pragma charmap (0x54, 0x54) +#pragma charmap (0x55, 0x55) +#pragma charmap (0x56, 0x56) +#pragma charmap (0x57, 0x57) +#pragma charmap (0x58, 0x58) +#pragma charmap (0x59, 0x59) +#pragma charmap (0x5A, 0x5A) +#pragma charmap (0x5B, 0x5B) +#pragma charmap (0x5C, 0x5C) +#pragma charmap (0x5D, 0x5D) +#pragma charmap (0x5E, 0x5E) +#pragma charmap (0x5F, 0x5F) +#pragma charmap (0x60, 0x60) +#pragma charmap (0x61, 0x61) +#pragma charmap (0x62, 0x62) +#pragma charmap (0x63, 0x63) +#pragma charmap (0x64, 0x64) +#pragma charmap (0x65, 0x65) +#pragma charmap (0x66, 0x66) +#pragma charmap (0x67, 0x67) +#pragma charmap (0x68, 0x68) +#pragma charmap (0x69, 0x69) +#pragma charmap (0x6A, 0x6A) +#pragma charmap (0x6B, 0x6B) +#pragma charmap (0x6C, 0x6C) +#pragma charmap (0x6D, 0x6D) +#pragma charmap (0x6E, 0x6E) +#pragma charmap (0x6F, 0x6F) +#pragma charmap (0x70, 0x70) +#pragma charmap (0x71, 0x71) +#pragma charmap (0x72, 0x72) +#pragma charmap (0x73, 0x73) +#pragma charmap (0x74, 0x74) +#pragma charmap (0x75, 0x75) +#pragma charmap (0x76, 0x76) +#pragma charmap (0x77, 0x77) +#pragma charmap (0x78, 0x78) +#pragma charmap (0x79, 0x79) +#pragma charmap (0x7A, 0x7A) +#pragma charmap (0x7B, 0x7B) +#pragma charmap (0x7C, 0x7C) +#pragma charmap (0x7D, 0x7D) +#pragma charmap (0x7E, 0x7E) +#pragma charmap (0x7F, 0x7F) +#pragma charmap (0x80, 0x80) +#pragma charmap (0x81, 0x81) +#pragma charmap (0x82, 0x82) +#pragma charmap (0x83, 0x83) +#pragma charmap (0x84, 0x84) +#pragma charmap (0x85, 0x85) +#pragma charmap (0x86, 0x86) +#pragma charmap (0x87, 0x87) +#pragma charmap (0x88, 0x88) +#pragma charmap (0x89, 0x89) +#pragma charmap (0x8A, 0x8A) +#pragma charmap (0x8B, 0x8B) +#pragma charmap (0x8C, 0x8C) +#pragma charmap (0x8D, 0x8D) +#pragma charmap (0x8E, 0x8E) +#pragma charmap (0x8F, 0x8F) +#pragma charmap (0x90, 0x90) +#pragma charmap (0x91, 0x91) +#pragma charmap (0x92, 0x92) +#pragma charmap (0x93, 0x93) +#pragma charmap (0x94, 0x94) +#pragma charmap (0x95, 0x95) +#pragma charmap (0x96, 0x96) +#pragma charmap (0x97, 0x97) +#pragma charmap (0x98, 0x98) +#pragma charmap (0x99, 0x99) +#pragma charmap (0x9A, 0x9A) +#pragma charmap (0x9B, 0x9B) +#pragma charmap (0x9C, 0x9C) +#pragma charmap (0x9D, 0x9D) +#pragma charmap (0x9E, 0x9E) +#pragma charmap (0x9F, 0x9F) +#pragma charmap (0xA0, 0xA0) +#pragma charmap (0xA1, 0xA1) +#pragma charmap (0xA2, 0xA2) +#pragma charmap (0xA3, 0xA3) +#pragma charmap (0xA4, 0xA4) +#pragma charmap (0xA5, 0xA5) +#pragma charmap (0xA6, 0xA6) +#pragma charmap (0xA7, 0xA7) +#pragma charmap (0xA8, 0xA8) +#pragma charmap (0xA9, 0xA9) +#pragma charmap (0xAA, 0xAA) +#pragma charmap (0xAB, 0xAB) +#pragma charmap (0xAC, 0xAC) +#pragma charmap (0xAD, 0xAD) +#pragma charmap (0xAE, 0xAE) +#pragma charmap (0xAF, 0xAF) +#pragma charmap (0xB0, 0xB0) +#pragma charmap (0xB1, 0xB1) +#pragma charmap (0xB2, 0xB2) +#pragma charmap (0xB3, 0xB3) +#pragma charmap (0xB4, 0xB4) +#pragma charmap (0xB5, 0xB5) +#pragma charmap (0xB6, 0xB6) +#pragma charmap (0xB7, 0xB7) +#pragma charmap (0xB8, 0xB8) +#pragma charmap (0xB9, 0xB9) +#pragma charmap (0xBA, 0xBA) +#pragma charmap (0xBB, 0xBB) +#pragma charmap (0xBC, 0xBC) +#pragma charmap (0xBD, 0xBD) +#pragma charmap (0xBE, 0xBE) +#pragma charmap (0xBF, 0xBF) +#pragma charmap (0xC0, 0xC0) +#pragma charmap (0xC1, 0xC1) +#pragma charmap (0xC2, 0xC2) +#pragma charmap (0xC3, 0xC3) +#pragma charmap (0xC4, 0xC4) +#pragma charmap (0xC5, 0xC5) +#pragma charmap (0xC6, 0xC6) +#pragma charmap (0xC7, 0xC7) +#pragma charmap (0xC8, 0xC8) +#pragma charmap (0xC9, 0xC9) +#pragma charmap (0xCA, 0xCA) +#pragma charmap (0xCB, 0xCB) +#pragma charmap (0xCC, 0xCC) +#pragma charmap (0xCD, 0xCD) +#pragma charmap (0xCE, 0xCE) +#pragma charmap (0xCF, 0xCF) +#pragma charmap (0xD0, 0xD0) +#pragma charmap (0xD1, 0xD1) +#pragma charmap (0xD2, 0xD2) +#pragma charmap (0xD3, 0xD3) +#pragma charmap (0xD4, 0xD4) +#pragma charmap (0xD5, 0xD5) +#pragma charmap (0xD6, 0xD6) +#pragma charmap (0xD7, 0xD7) +#pragma charmap (0xD8, 0xD8) +#pragma charmap (0xD9, 0xD9) +#pragma charmap (0xDA, 0xDA) +#pragma charmap (0xDB, 0xDB) +#pragma charmap (0xDC, 0xDC) +#pragma charmap (0xDD, 0xDD) +#pragma charmap (0xDE, 0xDE) +#pragma charmap (0xDF, 0xDF) +#pragma charmap (0xE0, 0xE0) +#pragma charmap (0xE1, 0xE1) +#pragma charmap (0xE2, 0xE2) +#pragma charmap (0xE3, 0xE3) +#pragma charmap (0xE4, 0xE4) +#pragma charmap (0xE5, 0xE5) +#pragma charmap (0xE6, 0xE6) +#pragma charmap (0xE7, 0xE7) +#pragma charmap (0xE8, 0xE8) +#pragma charmap (0xE9, 0xE9) +#pragma charmap (0xEA, 0xEA) +#pragma charmap (0xEB, 0xEB) +#pragma charmap (0xEC, 0xEC) +#pragma charmap (0xED, 0xED) +#pragma charmap (0xEE, 0xEE) +#pragma charmap (0xEF, 0xEF) +#pragma charmap (0xF0, 0xF0) +#pragma charmap (0xF1, 0xF1) +#pragma charmap (0xF2, 0xF2) +#pragma charmap (0xF3, 0xF3) +#pragma charmap (0xF4, 0xF4) +#pragma charmap (0xF5, 0xF5) +#pragma charmap (0xF6, 0xF6) +#pragma charmap (0xF7, 0xF7) +#pragma charmap (0xF8, 0xF8) +#pragma charmap (0xF9, 0xF9) +#pragma charmap (0xFA, 0xFA) +#pragma charmap (0xFB, 0xFB) +#pragma charmap (0xFC, 0xFC) +#pragma charmap (0xFD, 0xFD) +#pragma charmap (0xFE, 0xFE) +#pragma charmap (0xFF, 0xFF) + +#pragma warn (remap-zero, pop) diff --git a/screen1.c b/screen1.c new file mode 100644 index 0000000..e2cc607 --- /dev/null +++ b/screen1.c @@ -0,0 +1,104 @@ +// SCREEN 1 VALUES + +// sprite patterns: $0000 +// pattern table: $0800 (256*8) +// sprite attributes: $1000 +// unused: $1080 +// name table: $1400 (32*24) +// unused: $1800 +// color table: $2000 (32) +// unused $2020-$3FFF + +#define SCREEN1_PATTERN_TABLE 0x0800 +#define SCREEN1_NAME_TABLE 0x1400 +#define SCREEN1_COLOR_TABLE 0x2000 +#define SCREEN1_SPRITE_PATTERNS 0x0000 +#define SCREEN1_SPRITE_ATTRS 0x1000 +#define SCREEN1_SIZE (32*24) + +byte SCREEN1_TABLE[8] = { + 0x00, 0xc0, 0x05, 0x80, 0x01, 0x20, 0x00, 0x25 +}; + +// loads the Laser 500 font on the pattern table +void SCREEN1_LOAD_FONT() { + + static byte *source = FONT; + static word i; + + // start writing into VRAM from "space" character + set_vram_addr(SCREEN1_PATTERN_TABLE+(32*8)); + for(i=0;i<768;i++) { + POKE(VDP_DATA, *source); + source++; + } + + source = FONT; + set_vram_addr(SCREEN1_PATTERN_TABLE+((128+32)*8)); + for(i=0;i<768;i++) { + POKE(VDP_DATA, ~(*source)); + source++; + } + + // TODO: inverted characters ? +} + +// prints character to TMS (SCREEN 1 MODE) +void fastcall SCREEN1_PUTCHAR(byte c) { + set_vram_addr(tms_cursor); + POKE(VDP_DATA, c); + tms_cursor++; +} + +// prints 0 terminated string pointed by YA +void SCREEN1_PUTS(char *s) { + byte c; + + while(1) { + c = *s; + // c = *s & 127; // TODO: explain why??? + if(c==0) return; + SCREEN1_PUTCHAR(c); + s++; + } +} + +void SCREEN1_HOME() { + tms_cursor = SCREEN1_NAME_TABLE; +} + +void SCREEN1_LOCATEXY(byte x, byte y) { + tms_cursor = SCREEN1_NAME_TABLE + ((word)y)*32 + x; +} + +void SCREEN1_INIT() { + static byte i; + for(i=0;i<8;i++) { + write_reg(i, SCREEN1_TABLE[i]); + } +} + +void SCREEN1_FILL() { + static word i; + + // fills name table with spaces (32) + set_vram_addr(SCREEN1_NAME_TABLE); + for(i=0;i> (x%8); + byte data; + + set_vram_read_addr(paddr); + data = PEEK(VDP_DATA); + set_vram_addr(paddr); + POKE(VDP_DATA,data | pattern); +} + +// int vti_abs(int x) { +// return x < 0 ? -x : x; +// } +// +// // http://members.chello.at/~easyfilter/bresenham.html +// void vti_ellipse_rect(int x0, int y0, int x1, int y1) +// { +// long a,b,b1,dx,dy,e2,err; +// +// a = vti_abs(x1-x0); +// b = vti_abs(y1-y0); +// b1 = b&1; /* values of diameter */ +// dx = 4*(1-a)*b*b; +// dy = 4*(b1+1)*a*a; /* error increment */ +// err = dx+dy+b1*a*a; /* error of 1.step */ +// +// if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */ +// if (y0 > y1) y0 = y1; /* .. exchange them */ +// y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */ +// a *= 8*a; b1 = 8*b*b; +// +// do { +// SCREEN2_PSET(x1, y0); /* I. Quadrant */ +// SCREEN2_PSET(x0, y0); /* II. Quadrant */ +// SCREEN2_PSET(x0, y1); /* III. Quadrant */ +// SCREEN2_PSET(x1, y1); /* IV. Quadrant */ +// e2 = 2*err; +// if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */ +// if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */ +// } while (x0 <= x1); +// +// while (y0-y1 < b) { /* too early stop of flat ellipses a=1 */ +// SCREEN2_PSET(x0-1, y0); /* -> finish tip of ellipse */ +// SCREEN2_PSET(x1+1, y0++); +// SCREEN2_PSET(x0-1, y1); +// SCREEN2_PSET(x1+1, y1--); +// } +// } diff --git a/test.c b/test.c index f6fe03c..30f18ae 100644 --- a/test.c +++ b/test.c @@ -1,7 +1,7 @@ #ifdef APPLE1 - #define WOZMON 0xFF1F // enters monitor - #define ECHO 0xFFEF // output ascii character in A (A not destroyed) - #define PRBYTE 0xFFDC // print hex byte in A (A destroyed) + #define WOZMON 0xFF1F // enters monitor + #define ECHO 0xFFEF // output ascii character in A (A not destroyed) + #define PRBYTE 0xFFDC // print hex byte in A (A destroyed) #define VDP_DATA 0xC000 // TMS9918 data port (VRAM) #define VDP_REG 0xC001 // TMS9918 register port (write) or status (read) #endif @@ -10,23 +10,29 @@ #define ECHO 0xFFD2 // chrout routine in kernal rom #define VDP_DATA 0xA000 // TMS9918 data port (VRAM) #define VDP_REG 0xA001 // TMS9918 register port (write) or status (read) + + #include "cbm_ascii_charmap.h" // allow VIC-20 to work with pure ASCII + #endif +// TMS9918 interface flags #define WRITE_TO_REG 0b10000000 #define WRITE_TO_VRAM 0b01000000 #define READ_FROM_VRAM 0b00000000 +// utils typedef unsigned char byte; typedef unsigned int word; #define POKE(a,b) (*((byte *)(a))=(byte)(b)) +#define PEEK(a) (*((byte *)(a))) // puts a character on the apple1 screen using the WOZMON routine void fastcall woz_putc(byte c) { asm("jsr %w", ECHO); } -// puts a character on the apple1 screen using the WOZMON routine +// returns to WOZMON prompt void woz_mon() { #ifdef APPLE1 asm("jmp %w", WOZMON); @@ -44,134 +50,41 @@ void fastcall set_vram_addr(word addr) { // nops here ? } -// writes a value to a TMS9918 register (0-7) -void write_reg(byte num, byte val) { - POKE(VDP_REG, val); - // nops here? - POKE(VDP_REG, (num & 0b00001111)|WRITE_TO_REG); - // nops here? +// sets the VRAM address on the TMS9918 +void fastcall set_vram_read_addr(word addr) { + asm("sta %w", VDP_REG); // write address low byte + // nops here ? + asm("txa"); // X = addres high byte + asm("and #%b", 0b00111111); // mask address high byte + asm("ora #%b", READ_FROM_VRAM); // set "write to vram" flag bits "01" upper bits ("00" for read) + asm("sta %w", VDP_REG); // write flags and address high byte + // nops here ? } -// SCREEN 1 VALUES - -// sprite patterns: $0000 -// pattern table: $0800 (256*8) -// sprite attributes: $1000 -// unused: $1080 -// name table: $1400 (32*24) -// unused: $1800 -// color table: $2000 (32) -// unused $2020-$3FFF - -#define PATTERN_TABLE 0x0800 -#define NAME_TABLE 0x1400 -#define COLOR_TABLE 0x2000 -#define SPRITE_PATTERNS 0x0000 -#define SPRITE_ATTRS 0x1000 - -#define SCREEN1_SIZE (32*24) - -byte SCREEN1_TABLE[8] = { - 0x00, 0xc0, 0x05, 0x80, 0x01, 0x20, 0x00, 0x25 -}; - -#include "laser500_font.ascii.c" - -// loads the Laser 500 font on the pattern table -void load_font() { - - static byte *source = FONT; - static word i; - - // start writing into VRAM from "space" character - set_vram_addr(PATTERN_TABLE+(32*8)); - for(i=0;i<768;i++) { - POKE(VDP_DATA, *source); - source++; - } - - source = FONT; - set_vram_addr(PATTERN_TABLE+((128+32)*8)); - for(i=0;i<768;i++) { - POKE(VDP_DATA, ~(*source)); - source++; - } - - // TODO: inverted characters ? +// writes a value to a TMS9918 register (0-7) +void write_reg(byte regnum, byte val) { + // nops are not required + POKE(VDP_REG, val); + POKE(VDP_REG, (regnum & 0b00001111)|WRITE_TO_REG); } static word tms_cursor; -// prints character to TMS (SCREEN 1 MODE) -void fastcall SCREEN1_PUTCHAR(byte c) { - set_vram_addr(tms_cursor); - POKE(VDP_DATA, c); - tms_cursor++; -} +#include "laser500_font.ascii.c" +#include "screen1.c" +#include "screen2.c" -// prints 0 terminated string pointed by YA -void SCREEN1_PUTS(char *s) { - byte c; - - while(1) { - c = *s & 127; // TODO: explain why??? - if(c==0) return; - SCREEN1_PUTCHAR(c); - s++; - } -} - -void SCREEN1_HOME() { - tms_cursor = NAME_TABLE; -} - -void SCREEN1_LOCATEXY(byte x, byte y) { - tms_cursor = NAME_TABLE + ((word)y)*32 + x; -} - -void INIT_SCREEN1() { - static byte i; - for(i=0;i<8;i++) { - write_reg(i, SCREEN1_TABLE[i]); - } -} - -void FILL_SCREEN1() { - static word i; - - // fills name table with spaces (32) - set_vram_addr(NAME_TABLE); - for(i=0;i