// TODO verificare NOPs #ifdef APPLE1 // APPLE1 #pragma start_address(0x4000) const word WOZMON = 0xFF1F; // enters monitor const word ECHO = 0xFFEF; // output ascii character in A (A not destroyed) const word PRBYTE = 0xFFDC; // print hex byte in A (A destroyed) const word KEY_DATA = 0xd010; // read key const word KEY_CTRL = 0xd011; // control port const word TERM_DATA = 0xd012; // write ascii const word TERM_CTRL = 0xd013; // control port const byte *VDP_DATA = 0xC000; // TMS9918 data port (VRAM) const byte *VDP_REG = 0xC001; // TMS9918 register port (write) or status (read) #else // VIC20 const word ECHO = 0xFFD2; // chrout routine in kernal rom const word GETIN = 0xFFE4; // GETIN keyboard read routine const byte *VDP_DATA = 0xA000; // TMS9918 data port (VRAM) const byte *VDP_REG = 0xA001; // TMS9918 register port (write) or status (read) #endif // typedef unsigned char byte; // typedef unsigned int word; // TMS9918 interface flags const byte WRITE_TO_REG = 0b10000000; const byte WRITE_TO_VRAM = 0b01000000; const byte READ_FROM_VRAM = 0b00000000; #define POKE(a,b) (*((byte *)(a))=(byte)(b)) #define PEEK(a) (*((byte *)(a))) #define NOP asm { nop } #define TMS_WRITE_REG(a) (*VDP_REG=(byte)(a)) #define TMS_WRITE_DATA(a) (*VDP_DATA=(byte)(a)) #define TMS_READ_REG (*VDP_REG); #define TMS_READ_DATA (*VDP_DATA); // status register #define FRAME_BIT(a) ((a) & 0b10000000) #define FIVESPR_BIT(a) ((a) & 0b01000000) #define COLLISION_BIT(a) ((a) & 0b00100000) #define SPRITE_NUM(a) ((a) & 0b00011111) // sets the VRAM write address on the TMS9918 void set_vram_write_addr(word addr) { TMS_WRITE_REG(addr & 0b00111111)|WRITE_TO_VRAM); } // sets the VRAM read address on the TMS9918 void set_vram_read_addr(word addr) { TMS_WRITE_REG(addr & 0b00111111)|READ_FROM_VRAM); } // writes a value to a TMS9918 register (0-7) void write_reg(byte regnum, byte val) { TMS_WRITE_REG(val); TMS_WRITE_REG((regnum & 0b00001111)|WRITE_TO_REG); } inline void set_color(byte col) { write_reg(7, col); } byte SCREEN1_TABLE[8] = { 0x00, 0xc0, 0x05, 0x80, 0x01, 0x20, 0x00, 0x25 }; byte SCREEN2_TABLE[8] = { 0x02, 0xc0, 0x0e, 0xff, 0x03, 0x76, 0x03, 0x25 }; /* IRQ on the apple1 goes to 0 - #pragma zp_reserve(0,1,2) - POKE 0,$4C (JUMP) - DOKE 1,address routine */ /* word tick_counts; __interrupt(hardware_all) void interrupt_handler() { tick_counts++; } // reserve locations for the IRQ vector #pragma zp_reserve(0,1,2) //__address(0x0001) volatile word KERNEL_IRQ; void install_interrupt() { asm { sei } POKE(0,0x4C); //KERNEL_IRQ = (word) &interrupt_handler; // *((word *)0x0001) = (word) &interrupt_handler; asm { cli } } */ word screen1_cursor; #include "laser500_font.ascii.c" // 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 const word SCREEN1_PATTERN_TABLE = 0x0800; const word SCREEN1_NAME_TABLE = 0x1400; const word SCREEN1_COLOR_TABLE = 0x2000; const word SCREEN1_SPRITE_PATTERNS = 0x0000; const word SCREEN1_SPRITE_ATTRS = 0x1000; const word SCREEN1_SIZE = (32*24); // 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 (32..127) set_vram_write_addr(SCREEN1_PATTERN_TABLE+(32*8)); for(i=768;i!=0;i--) { TMS_WRITE_DATA(*source++); } // reverse font (32..127) source = FONT; set_vram_write_addr(SCREEN1_PATTERN_TABLE+((128+32)*8)); for(i=768;i!=0;i--) { TMS_WRITE_DATA(~(*source++)); } } // prints character to TMS (SCREEN 1 MODE) void SCREEN1_PUTCHAR(byte c) { set_vram_write_addr(screen1_cursor++); TMS_WRITE_DATA(c); } // prints 0 terminated string pointed by YA void SCREEN1_PUTS(byte *s) { byte c; while(c=*s++) { SCREEN1_PUTCHAR(c); } } void SCREEN1_HOME() { screen1_cursor = SCREEN1_NAME_TABLE; } void SCREEN1_LOCATEXY(byte x, byte y) { screen1_cursor = SCREEN1_NAME_TABLE + ((word)y)*32 + x; } void SCREEN1_FILL() { // fills name table with spaces (32) set_vram_write_addr(SCREEN1_NAME_TABLE); for(word i=SCREEN1_SIZE;i!=0;i--) { TMS_WRITE_DATA(32); } // fill pattern table with 0 set_vram_write_addr(SCREEN1_PATTERN_TABLE); for(word i=256*8;i!=0;i--) { TMS_WRITE_DATA(0); } // fill color table with $1F set_vram_write_addr(SCREEN1_COLOR_TABLE); for(byte i=32;i!=0;i--) { TMS_WRITE_DATA(0x1f); } } // SCREEN 2 VALUES // pattern table: $0000-$17FF (256*8*3) // sprite patterns: $1800-$19FF // color table: $2000-$27FF (256*8*3) // name table: $3800-$3AFF (32*24 = 256*3 = 768) // sprite attributes: $3B00-$3BFF // unused $3C00-$3FFF // const word SCREEN2_PATTERN_TABLE = 0x0000; const word SCREEN2_NAME_TABLE = 0x3800; const word SCREEN2_COLOR_TABLE = 0x2000; const word SCREEN2_SPRITE_PATTERNS = 0x1800; const word SCREEN2_SPRITE_ATTRS = 0x3b00; const word SCREEN2_SIZE = (32*24); void SCREEN_INIT(byte *table) { for(byte i=0;i<8;i++) { write_reg(i, table[i]); } } void SCREEN2_FILL() { // fills name table x3 with increasing numbers set_vram_write_addr(SCREEN2_NAME_TABLE); for(word i=0;i= dy) { err += dy; if(ix) ++x0; else --x0; } /* e_xy+e_x > 0 */ if (e2 <= dx) { err += dx; if(iy) ++y0; else --y0; } /* e_xy+e_y < 0 */ } } /* // http://members.chello.at/~easyfilter/bresenham.html void vti_ellipse_rect(byte _x0, byte _y0, byte _x1, byte _y1) { //unsigned int x0,y0,x1,y1; signed int x0 = (signed int) _x0; signed int y0 = (signed int) _y0; signed int x1 = (signed int) _x1; signed int y1 = (signed int) _y1; signed int a = vti_abs(x1-x0), b = vti_abs(y1-y0); signed int b1 = b&1; // values of diameter signed int dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; // error increment signed int err = dx+dy+b1*a*a, e2; // 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_PLOT((byte) x1, (byte) y0); // I. Quadrant SCREEN2_PLOT((byte) x0, (byte) y0); // II. Quadrant SCREEN2_PLOT((byte) x0, (byte) y1); // III. Quadrant SCREEN2_PLOT((byte) x1, (byte) 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_PLOT((byte) x0-1, (byte) (y0)); // -> finish tip of ellipse SCREEN2_PLOT((byte) x1+1, (byte) (y0++)); SCREEN2_PLOT((byte) x0-1, (byte) (y1)); SCREEN2_PLOT((byte) x1+1, (byte) (y1--)); } } */ void main() { //install_interrupt(); byte key = '1'; for(;;) { if(key == '1') prova_screen1(); else if(key == '2') prova_screen2(); else if(key == '3') prova_screen3(); else if(key == '0') break; else woz_putc(key); key = woz_getkey(); } woz_putc(42); woz_mon(); }