mirror of
https://github.com/nippur72/apple1-videocard-lib.git
synced 2024-06-25 23:29:36 +00:00
switch to KickC compiler
This commit is contained in:
parent
52c825f19b
commit
f7fe27e98b
|
@ -1,6 +0,0 @@
|
||||||
@echo *** APPLE 1 ***
|
|
||||||
call kickc -t asm6502 -D=APPLE1 test.c -o test_apple1.prg -e
|
|
||||||
copy test.prg test_apple1.prg
|
|
||||||
@echo *** VIC20 ***
|
|
||||||
call kickc -t VIC20 -D=VIC20 test.c -o test_vic20.prg -e
|
|
||||||
copy test.prg test_vic20.prg
|
|
305
KickC/test.c
305
KickC/test.c
|
@ -1,305 +0,0 @@
|
||||||
#ifdef APPLE1
|
|
||||||
// APPLE1
|
|
||||||
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 VDP_DATA = 0xC000; // TMS9918 data port (VRAM)
|
|
||||||
const word VDP_REG = 0xC001; // TMS9918 register port (write) or status (read)
|
|
||||||
#else
|
|
||||||
// VIC20
|
|
||||||
const word ECHO = 0xFFD2; // chrout routine in kernal rom
|
|
||||||
const word VDP_DATA = 0xA000; // TMS9918 data port (VRAM)
|
|
||||||
const word 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)))
|
|
||||||
|
|
||||||
// puts a character on the apple1 screen using the WOZMON routine
|
|
||||||
void woz_putc(byte c) {
|
|
||||||
asm {
|
|
||||||
lda c
|
|
||||||
jsr ECHO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns to WOZMON prompt
|
|
||||||
void woz_mon() {
|
|
||||||
#ifdef APPLE1
|
|
||||||
asm {
|
|
||||||
jmp WOZMON
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// sets the VRAM address on the TMS9918
|
|
||||||
void set_vram_addr(word addr) {
|
|
||||||
POKE(VDP_REG,<addr);
|
|
||||||
POKE(VDP_REG,(>addr & 0b00111111)|WRITE_TO_VRAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sets the VRAM address on the TMS9918
|
|
||||||
void set_vram_read_addr(word addr) {
|
|
||||||
POKE(VDP_REG,<addr);
|
|
||||||
POKE(VDP_REG,(>addr & 0b00111111)|READ_FROM_VRAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
word tms_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);
|
|
||||||
|
|
||||||
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++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reverse font
|
|
||||||
source = FONT;
|
|
||||||
set_vram_addr(SCREEN1_PATTERN_TABLE+((128+32)*8));
|
|
||||||
for(i=0;i<768;i++) {
|
|
||||||
POKE(VDP_DATA, ~(*source++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prints character to TMS (SCREEN 1 MODE)
|
|
||||||
void SCREEN1_PUTCHAR(byte c) {
|
|
||||||
set_vram_addr(tms_cursor++);
|
|
||||||
POKE(VDP_DATA, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// prints 0 terminated string pointed by YA
|
|
||||||
void SCREEN1_PUTS(byte *s) {
|
|
||||||
while(*s) {
|
|
||||||
SCREEN1_PUTCHAR(*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() {
|
|
||||||
for(byte i=0;i<8;i++) {
|
|
||||||
write_reg(i, SCREEN1_TABLE[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SCREEN1_FILL() {
|
|
||||||
// fills name table with spaces (32)
|
|
||||||
set_vram_addr(SCREEN1_NAME_TABLE);
|
|
||||||
for(word i=0;i<SCREEN1_SIZE;i++) {
|
|
||||||
POKE(VDP_DATA, 32);
|
|
||||||
// nops here?
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill pattern table with 0
|
|
||||||
set_vram_addr(SCREEN1_PATTERN_TABLE);
|
|
||||||
for(word i=0;i<256*8;i++) {
|
|
||||||
POKE(VDP_DATA, 0);
|
|
||||||
// nops here?
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill color table with $1F
|
|
||||||
set_vram_addr(SCREEN1_COLOR_TABLE);
|
|
||||||
for(byte i=0;i<32;i++) {
|
|
||||||
POKE(VDP_DATA, 0x1f);
|
|
||||||
// nops here?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
byte SCREEN2_TABLE[8] = {
|
|
||||||
0x02, 0xc0, 0x0e, 0xff, 0x03, 0x76, 0x03, 0x25
|
|
||||||
};
|
|
||||||
|
|
||||||
void SCREEN2_INIT() {
|
|
||||||
for(byte i=0;i<8;i++) {
|
|
||||||
write_reg(i, SCREEN2_TABLE[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SCREEN2_FILL() {
|
|
||||||
// fills name table x3 with increasing numbers
|
|
||||||
set_vram_addr(SCREEN2_NAME_TABLE);
|
|
||||||
for(word i=0;i<SCREEN2_SIZE;i++) {
|
|
||||||
POKE(VDP_DATA, i & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill pattern table with 0 (clear screen)
|
|
||||||
set_vram_addr(SCREEN2_PATTERN_TABLE);
|
|
||||||
for(word i=0;i<768*8;i++) {
|
|
||||||
POKE(VDP_DATA, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill color table with $1F
|
|
||||||
set_vram_addr(SCREEN2_COLOR_TABLE);
|
|
||||||
for(word i=0;i<768*8;i++) {
|
|
||||||
POKE(VDP_DATA, 0x1f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SCREEN2_PUTC(byte ch, byte x, byte y, byte col) {
|
|
||||||
byte *source = &FONT[(word)(ch-32)*8];
|
|
||||||
word paddr = SCREEN2_PATTERN_TABLE + x*8 + y*256;
|
|
||||||
word caddr = SCREEN2_COLOR_TABLE + x*8 + y*256;
|
|
||||||
|
|
||||||
set_vram_addr(paddr); for(byte i=0;i<8;i++) POKE(VDP_DATA, source[i]);
|
|
||||||
set_vram_addr(caddr); for(byte i=0;i<8;i++) POKE(VDP_DATA, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SCREEN2_PUTS(byte x, byte y, byte col, char *s) {
|
|
||||||
while(*s) {
|
|
||||||
SCREEN2_PUTC(*s++, x++, y, col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SCREEN2_PSET(byte x, byte y) {
|
|
||||||
word paddr = SCREEN2_PATTERN_TABLE + (word)(x & 0b11111000) + (word)(y & 0b11111000)*32 + y%8;
|
|
||||||
byte pattern = 128 >> (x%8);
|
|
||||||
byte data;
|
|
||||||
|
|
||||||
set_vram_read_addr(paddr);
|
|
||||||
data = PEEK(VDP_DATA);
|
|
||||||
set_vram_addr(paddr);
|
|
||||||
POKE(VDP_DATA,data | pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
void screen1_square_sprites() {
|
|
||||||
// fills first sprite pattern with 255
|
|
||||||
set_vram_addr(SCREEN1_SPRITE_PATTERNS); // start writing in the sprite patterns
|
|
||||||
for(byte i=0;i<8;i++) {
|
|
||||||
POKE(VDP_DATA, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set sprite coordinates
|
|
||||||
set_vram_addr(SCREEN1_SPRITE_ATTRS); // start writing in the sprite attribute
|
|
||||||
for(byte i=0;i<32;i++) {
|
|
||||||
POKE(VDP_DATA,(6+i)*8); // y coordinate
|
|
||||||
POKE(VDP_DATA,(6+i)*8); // x coordinate
|
|
||||||
POKE(VDP_DATA,0); // name
|
|
||||||
POKE(VDP_DATA,i); // color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void screen2_square_sprites() {
|
|
||||||
// fills first sprite pattern with 255
|
|
||||||
set_vram_addr(SCREEN2_SPRITE_PATTERNS); // start writing in the sprite patterns
|
|
||||||
for(byte i=0;i<8;i++) {
|
|
||||||
POKE(VDP_DATA, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set sprite coordinates
|
|
||||||
set_vram_addr(SCREEN2_SPRITE_ATTRS); // start writing in the sprite attribute
|
|
||||||
for(byte i=0;i<32;i++) {
|
|
||||||
POKE(VDP_DATA,0); // y coordinate
|
|
||||||
POKE(VDP_DATA,0); // x coordinate
|
|
||||||
POKE(VDP_DATA,0); // name
|
|
||||||
POKE(VDP_DATA,i); // color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
if(1) {
|
|
||||||
SCREEN1_INIT();
|
|
||||||
SCREEN1_FILL();
|
|
||||||
SCREEN1_LOAD_FONT();
|
|
||||||
|
|
||||||
SCREEN1_HOME(); SCREEN1_PUTS("*** P-LAB VIDEO CARD SYSTEM ***");
|
|
||||||
SCREEN1_LOCATEXY(0, 2); SCREEN1_PUTS("16K VRAM BYTES FREE");
|
|
||||||
SCREEN1_LOCATEXY(0, 4); SCREEN1_PUTS("READY.");
|
|
||||||
|
|
||||||
SCREEN1_LOCATEXY(0, 10);
|
|
||||||
for(word i=0;i<256;i++) SCREEN1_PUTCHAR((byte)i);
|
|
||||||
|
|
||||||
screen1_square_sprites();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(0) {
|
|
||||||
SCREEN2_INIT();
|
|
||||||
SCREEN2_FILL();
|
|
||||||
screen2_square_sprites();
|
|
||||||
//SCREEN2_PUTC(65,1,1,0x1F);
|
|
||||||
|
|
||||||
SCREEN2_PUTS(0,0,0x1F,"*** P-LAB VIDEO CARD SYSTEM ***");
|
|
||||||
SCREEN2_PUTS(0,2,0x1F,"16K VRAM BYTES FREE");
|
|
||||||
SCREEN2_PUTS(0,4,0x1F,"READY.");
|
|
||||||
|
|
||||||
for(byte i=0;i<16;i++) {
|
|
||||||
SCREEN2_PUTS(5,(byte)(6+i),(byte)(((15-i)<<4)+i)," COLOR ");
|
|
||||||
}
|
|
||||||
|
|
||||||
for(byte i=0;i<192;i++) {
|
|
||||||
SCREEN2_PSET((byte)i ,(byte)i/2);
|
|
||||||
SCREEN2_PSET((byte)i ,(byte)i);
|
|
||||||
SCREEN2_PSET((byte)i/2,(byte)i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
woz_putc(42);
|
|
||||||
woz_mon();
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,10 +4,10 @@ Library and demos for the Apple-1 TMS9918 video card by P-LAB.
|
||||||
|
|
||||||
# USAGE (Windows)
|
# USAGE (Windows)
|
||||||
|
|
||||||
- `env.bat` sets CC65 path variable (run it once)
|
- `env_kick.bat` sets KickC compiler path variable (run it once)
|
||||||
- `c.bat` compiles `test.c` for both VIC-20 and Apple-1
|
- `c.bat` compiles `test.c` for both VIC-20 and Apple-1
|
||||||
- `test_vic20.prg` runs on the "hybrid" VIC-20 emulator
|
- `test_vic20.prg` runs on the "hybrid" VIC-20 emulator
|
||||||
- `node hexdump` gives the output in WOZMON format for the Apple-1
|
- `node hexdump` puts `test_apple1.prg` into WOZMON format for the Apple-1
|
||||||
|
|
||||||
Note: Apple-1 start address is $4000, with TMS address range $C000-$C001
|
Note: Apple-1 start address is $4000, with TMS address range $C000-$C001
|
||||||
|
|
||||||
|
|
10
c.bat
10
c.bat
|
@ -1,4 +1,8 @@
|
||||||
cl65 -D APPLE1 --target none --start-addr $4000 -O test.c -o test_apple1.prg
|
@echo ======================== APPLE 1 =================================================
|
||||||
cl65 --listing test.lst -D VIC20 --target vic20 -O test.c -o test_vic20.prg
|
call kickc -t asm6502 -D=APPLE1 test.c -o test_apple1.prg -e
|
||||||
|
copy test.prg test_apple1.prg
|
||||||
|
@echo ======================== VIC20 ===================================================
|
||||||
|
call kickc -t VIC20 -D=VIC20 test.c -o test_vic20.prg -e
|
||||||
|
rem call kickc -vasmoptimize -vasmout -vcreate -vfragment -vliverange -vloop -vnonoptimize -voptimize -vparse -vsequence -vsizeinfo -vunroll -vuplift -t VIC20 -D=VIC20 test.c -o test_vic20.prg -e
|
||||||
|
copy test.prg test_vic20.prg
|
||||||
|
|
||||||
|
|
4
cc65/c.bat
Normal file
4
cc65/c.bat
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
cl65 -D APPLE1 --target none --start-addr $4000 -O test.c -o test_apple1.prg
|
||||||
|
cl65 --listing test.lst -D VIC20 --target vic20 -O test.c -o test_vic20.prg
|
||||||
|
|
||||||
|
|
157
cc65/test.c
Normal file
157
cc65/test.c
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
#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 VDP_DATA 0xC000 // TMS9918 data port (VRAM)
|
||||||
|
#define VDP_REG 0xC001 // TMS9918 register port (write) or status (read)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VIC20
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns to WOZMON prompt
|
||||||
|
void woz_mon() {
|
||||||
|
#ifdef APPLE1
|
||||||
|
asm("jmp %w", WOZMON);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the VRAM address on the TMS9918
|
||||||
|
void fastcall set_vram_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", WRITE_TO_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 ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
#include "laser500_font.ascii.c"
|
||||||
|
#include "screen1.c"
|
||||||
|
#include "screen2.c"
|
||||||
|
|
||||||
|
void screen1_square_sprites() {
|
||||||
|
static byte i;
|
||||||
|
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
set_vram_addr(SCREEN1_SPRITE_PATTERNS); // start writing in the sprite patterns
|
||||||
|
for(i=0;i<8;i++) {
|
||||||
|
POKE(VDP_DATA, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set sprite coordinates
|
||||||
|
set_vram_addr(SCREEN1_SPRITE_ATTRS); // start writing in the sprite attribute
|
||||||
|
for(i=0;i<32;i++) {
|
||||||
|
POKE(VDP_DATA,(6+i)*8); // y coordinate
|
||||||
|
POKE(VDP_DATA,(6+i)*8); // x coordinate
|
||||||
|
POKE(VDP_DATA,0); // name
|
||||||
|
POKE(VDP_DATA,i); // color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen2_square_sprites() {
|
||||||
|
static byte i;
|
||||||
|
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
set_vram_addr(SCREEN2_SPRITE_PATTERNS); // start writing in the sprite patterns
|
||||||
|
for(i=0;i<8;i++) {
|
||||||
|
POKE(VDP_DATA, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set sprite coordinates
|
||||||
|
set_vram_addr(SCREEN2_SPRITE_ATTRS); // start writing in the sprite attribute
|
||||||
|
for(i=0;i<32;i++) {
|
||||||
|
POKE(VDP_DATA,0); // y coordinate
|
||||||
|
POKE(VDP_DATA,0); // x coordinate
|
||||||
|
POKE(VDP_DATA,0); // name
|
||||||
|
POKE(VDP_DATA,i); // color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
word i;
|
||||||
|
|
||||||
|
if(0) {
|
||||||
|
SCREEN1_INIT();
|
||||||
|
SCREEN1_FILL();
|
||||||
|
SCREEN1_LOAD_FONT();
|
||||||
|
|
||||||
|
SCREEN1_HOME(); SCREEN1_PUTS("*** P-LAB VIDEO CARD SYSTEM ***");
|
||||||
|
SCREEN1_LOCATEXY(0, 2); SCREEN1_PUTS("16K VRAM BYTES FREE");
|
||||||
|
SCREEN1_LOCATEXY(0, 4); SCREEN1_PUTS("READY.");
|
||||||
|
|
||||||
|
SCREEN1_LOCATEXY(0, 10);
|
||||||
|
for(i=0;i<256;i++) SCREEN1_PUTCHAR(i);
|
||||||
|
|
||||||
|
screen1_square_sprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1) {
|
||||||
|
SCREEN2_INIT();
|
||||||
|
SCREEN2_FILL();
|
||||||
|
screen2_square_sprites();
|
||||||
|
//SCREEN2_PUTC(65,1,1,0x1F);
|
||||||
|
|
||||||
|
SCREEN2_PUTS(0,0,0x1F,"*** P-LAB VIDEO CARD SYSTEM ***");
|
||||||
|
SCREEN2_PUTS(0,2,0x1F,"16K VRAM BYTES FREE");
|
||||||
|
SCREEN2_PUTS(0,4,0x1F,"READY.");
|
||||||
|
|
||||||
|
for(i=0;i<16;i++) {
|
||||||
|
SCREEN2_PUTS(5,6+i,((15-i)<<4)+i," COLOR ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<192;i++) {
|
||||||
|
SCREEN2_PSET(i,i/2);
|
||||||
|
SCREEN2_PSET(i,i);
|
||||||
|
SCREEN2_PSET(i/2,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
woz_putc(42);
|
||||||
|
woz_mon();
|
||||||
|
}
|
||||||
|
|
389
test.c
389
test.c
|
@ -1,156 +1,337 @@
|
||||||
|
// TODO verificare NOPs
|
||||||
|
|
||||||
#ifdef APPLE1
|
#ifdef APPLE1
|
||||||
#define WOZMON 0xFF1F // enters monitor
|
// APPLE1
|
||||||
#define ECHO 0xFFEF // output ascii character in A (A not destroyed)
|
#pragma start_address(0x4000)
|
||||||
#define PRBYTE 0xFFDC // print hex byte in A (A destroyed)
|
const word WOZMON = 0xFF1F; // enters monitor
|
||||||
#define VDP_DATA 0xC000 // TMS9918 data port (VRAM)
|
const word ECHO = 0xFFEF; // output ascii character in A (A not destroyed)
|
||||||
#define VDP_REG 0xC001 // TMS9918 register port (write) or status (read)
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef VIC20
|
// typedef unsigned char byte;
|
||||||
#define ECHO 0xFFD2 // chrout routine in kernal rom
|
// typedef unsigned int word;
|
||||||
#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
|
// TMS9918 interface flags
|
||||||
#define WRITE_TO_REG 0b10000000
|
const byte WRITE_TO_REG = 0b10000000;
|
||||||
#define WRITE_TO_VRAM 0b01000000
|
const byte WRITE_TO_VRAM = 0b01000000;
|
||||||
#define READ_FROM_VRAM 0b00000000
|
const byte READ_FROM_VRAM = 0b00000000;
|
||||||
|
|
||||||
// utils
|
|
||||||
typedef unsigned char byte;
|
|
||||||
typedef unsigned int word;
|
|
||||||
|
|
||||||
#define POKE(a,b) (*((byte *)(a))=(byte)(b))
|
#define POKE(a,b) (*((byte *)(a))=(byte)(b))
|
||||||
#define PEEK(a) (*((byte *)(a)))
|
#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_DATA (*VDP_DATA);
|
||||||
|
|
||||||
// puts a character on the apple1 screen using the WOZMON routine
|
// puts a character on the apple1 screen using the WOZMON routine
|
||||||
void fastcall woz_putc(byte c) {
|
void woz_putc(byte c) {
|
||||||
asm("jsr %w", ECHO);
|
asm {
|
||||||
|
lda c
|
||||||
|
jsr ECHO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns to WOZMON prompt
|
// returns to WOZMON prompt
|
||||||
void woz_mon() {
|
void woz_mon() {
|
||||||
#ifdef APPLE1
|
#ifdef APPLE1
|
||||||
asm("jmp %w", WOZMON);
|
asm {
|
||||||
|
jmp WOZMON
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the VRAM address on the TMS9918
|
// reads a key from the apple-1 keyboard
|
||||||
void fastcall set_vram_addr(word addr) {
|
byte woz_getkey() {
|
||||||
asm("sta %w", VDP_REG); // write address low byte
|
#ifdef APPLE1
|
||||||
// nops here ?
|
while((unsigned byte)PEEK(KEY_CTRL)>0);
|
||||||
asm("txa"); // X = addres high byte
|
return PEEK(KEY_DATA) & 0x7f;
|
||||||
asm("and #%b", 0b00111111); // mask address high byte
|
#else
|
||||||
asm("ora #%b", WRITE_TO_VRAM); // set "write to vram" flag bits "01" upper bits ("00" for read)
|
byte key;
|
||||||
asm("sta %w", VDP_REG); // write flags and address high byte
|
byte const *keyptr = &key;
|
||||||
// nops here ?
|
kickasm(uses keyptr, uses GETIN) {{
|
||||||
|
__wait:
|
||||||
|
jsr GETIN
|
||||||
|
cmp #0
|
||||||
|
beq __wait
|
||||||
|
sta keyptr
|
||||||
|
}}
|
||||||
|
return key;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the VRAM address on the TMS9918
|
// sets the VRAM write address on the TMS9918
|
||||||
void fastcall set_vram_read_addr(word addr) {
|
void set_vram_write_addr(word addr) {
|
||||||
asm("sta %w", VDP_REG); // write address low byte
|
TMS_WRITE_REG(<addr);
|
||||||
// nops here ?
|
TMS_WRITE_REG((>addr & 0b00111111)|WRITE_TO_VRAM);
|
||||||
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)
|
// sets the VRAM read address on the TMS9918
|
||||||
asm("sta %w", VDP_REG); // write flags and address high byte
|
void set_vram_read_addr(word addr) {
|
||||||
// nops here ?
|
TMS_WRITE_REG(<addr);
|
||||||
|
TMS_WRITE_REG((>addr & 0b00111111)|READ_FROM_VRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes a value to a TMS9918 register (0-7)
|
// writes a value to a TMS9918 register (0-7)
|
||||||
void write_reg(byte regnum, byte val) {
|
void write_reg(byte regnum, byte val) {
|
||||||
// nops are not required
|
// nops are not required
|
||||||
POKE(VDP_REG, val);
|
TMS_WRITE_REG(val);
|
||||||
POKE(VDP_REG, (regnum & 0b00001111)|WRITE_TO_REG);
|
TMS_WRITE_REG((regnum & 0b00001111)|WRITE_TO_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static word tms_cursor;
|
word screen1_cursor;
|
||||||
|
|
||||||
#include "laser500_font.ascii.c"
|
#include "laser500_font.ascii.c"
|
||||||
#include "screen1.c"
|
|
||||||
#include "screen2.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);
|
||||||
|
|
||||||
|
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 (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);
|
||||||
|
|
||||||
|
byte SCREEN2_TABLE[8] = {
|
||||||
|
0x02, 0xc0, 0x0e, 0xff, 0x03, 0x76, 0x03, 0x25
|
||||||
|
};
|
||||||
|
|
||||||
|
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<SCREEN2_SIZE;i++) {
|
||||||
|
TMS_WRITE_DATA(i & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill pattern table with 0 (clear screen)
|
||||||
|
set_vram_write_addr(SCREEN2_PATTERN_TABLE);
|
||||||
|
for(word i=768*8;i!=0;i--) {
|
||||||
|
TMS_WRITE_DATA(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill color table with $1F
|
||||||
|
set_vram_write_addr(SCREEN2_COLOR_TABLE);
|
||||||
|
for(word i=768*8;i!=0;i--) {
|
||||||
|
TMS_WRITE_DATA(0x1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCREEN2_PUTC(byte ch, byte x, byte y, byte col) {
|
||||||
|
byte *source = &FONT[(word)(ch-32)*8];
|
||||||
|
word addr = x*8 + y*256;
|
||||||
|
set_vram_write_addr(SCREEN2_PATTERN_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA(source[i]);
|
||||||
|
set_vram_write_addr(SCREEN2_COLOR_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCREEN2_PUTS(byte x, byte y, byte col, char *s) {
|
||||||
|
byte c;
|
||||||
|
while(c=*s++) {
|
||||||
|
SCREEN2_PUTC(c, x++, y, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCREEN2_PSET(byte x, byte y) {
|
||||||
|
static byte pow2_table[8] = { 128,64,32,16,8,4,2,1 };
|
||||||
|
word paddr = SCREEN2_PATTERN_TABLE + (word)(x & 0b11111000) + (word)(y & 0b11111000)*32 + y%8;
|
||||||
|
set_vram_read_addr(paddr);
|
||||||
|
byte data = TMS_READ_DATA;
|
||||||
|
set_vram_write_addr(paddr);
|
||||||
|
TMS_WRITE_DATA(data|pow2_table[x%8]);
|
||||||
|
}
|
||||||
|
|
||||||
void screen1_square_sprites() {
|
void screen1_square_sprites() {
|
||||||
static byte i;
|
|
||||||
|
|
||||||
// fills first sprite pattern with 255
|
// fills first sprite pattern with 255
|
||||||
set_vram_addr(SCREEN1_SPRITE_PATTERNS); // start writing in the sprite patterns
|
set_vram_write_addr(SCREEN1_SPRITE_PATTERNS); // start writing in the sprite patterns
|
||||||
for(i=0;i<8;i++) {
|
for(byte i=0;i<8;i++) {
|
||||||
POKE(VDP_DATA, 255);
|
TMS_WRITE_DATA(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set sprite coordinates
|
// set sprite coordinates
|
||||||
set_vram_addr(SCREEN1_SPRITE_ATTRS); // start writing in the sprite attribute
|
set_vram_write_addr(SCREEN1_SPRITE_ATTRS); // start writing in the sprite attribute
|
||||||
for(i=0;i<32;i++) {
|
for(byte i=0;i<32;i++) {
|
||||||
POKE(VDP_DATA,(6+i)*8); // y coordinate
|
TMS_WRITE_DATA((6+i)*8); // y coordinate
|
||||||
POKE(VDP_DATA,(6+i)*8); // x coordinate
|
TMS_WRITE_DATA((6+i)*8); // x coordinate
|
||||||
POKE(VDP_DATA,0); // name
|
TMS_WRITE_DATA(0); // name
|
||||||
POKE(VDP_DATA,i); // color
|
TMS_WRITE_DATA(i); // color
|
||||||
|
// TODO: nops here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen2_square_sprites() {
|
void screen2_square_sprites() {
|
||||||
static byte i;
|
|
||||||
|
|
||||||
// fills first sprite pattern with 255
|
// fills first sprite pattern with 255
|
||||||
set_vram_addr(SCREEN2_SPRITE_PATTERNS); // start writing in the sprite patterns
|
set_vram_write_addr(SCREEN2_SPRITE_PATTERNS); // start writing in the sprite patterns
|
||||||
for(i=0;i<8;i++) {
|
for(byte i=0;i<8;i++) {
|
||||||
POKE(VDP_DATA, 0);
|
TMS_WRITE_DATA(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set sprite coordinates
|
// set sprite coordinates
|
||||||
set_vram_addr(SCREEN2_SPRITE_ATTRS); // start writing in the sprite attribute
|
set_vram_write_addr(SCREEN2_SPRITE_ATTRS); // start writing in the sprite attribute
|
||||||
for(i=0;i<32;i++) {
|
for(byte i=0;i<32;i++) {
|
||||||
POKE(VDP_DATA,0); // y coordinate
|
TMS_WRITE_DATA(0); // y coordinate
|
||||||
POKE(VDP_DATA,0); // x coordinate
|
TMS_WRITE_DATA(0); // x coordinate
|
||||||
POKE(VDP_DATA,0); // name
|
TMS_WRITE_DATA(0); // name
|
||||||
POKE(VDP_DATA,i); // color
|
TMS_WRITE_DATA(i); // color
|
||||||
|
// TODO: nops here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void prova_screen1() {
|
||||||
|
SCREEN_INIT(SCREEN1_TABLE);
|
||||||
|
SCREEN1_FILL();
|
||||||
|
SCREEN1_LOAD_FONT();
|
||||||
|
|
||||||
|
SCREEN1_HOME(); SCREEN1_PUTS("*** P-LAB VIDEO CARD SYSTEM ***");
|
||||||
|
SCREEN1_LOCATEXY(0, 2); SCREEN1_PUTS("16K VRAM BYTES FREE");
|
||||||
|
SCREEN1_LOCATEXY(0, 4); SCREEN1_PUTS("READY.");
|
||||||
|
|
||||||
|
SCREEN1_LOCATEXY(0, 10);
|
||||||
|
for(word i=0;i<256;i++) SCREEN1_PUTCHAR((byte)i);
|
||||||
|
|
||||||
|
screen1_square_sprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
void prova_screen2() {
|
||||||
|
SCREEN_INIT(SCREEN2_TABLE);
|
||||||
|
SCREEN2_FILL();
|
||||||
|
screen2_square_sprites();
|
||||||
|
|
||||||
|
SCREEN2_PUTS(0,0,0x1F,"*** P-LAB VIDEO CARD SYSTEM ***");
|
||||||
|
SCREEN2_PUTS(0,2,0x1F,"16K VRAM BYTES FREE");
|
||||||
|
SCREEN2_PUTS(0,4,0x1F,"READY.");
|
||||||
|
|
||||||
|
for(byte i=0;i<16;i++) {
|
||||||
|
SCREEN2_PUTS(5,(byte)(6+i),(byte)(((15-i)<<4)+i)," SCREEN 2 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(byte i=0;i<192;i++) {
|
||||||
|
SCREEN2_PSET((byte)i ,(byte)i/2);
|
||||||
|
SCREEN2_PSET((byte)i ,(byte)i);
|
||||||
|
SCREEN2_PSET((byte)i/2,(byte)i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
word i;
|
byte key = '1';
|
||||||
|
for(;;) {
|
||||||
|
if(key == '1') prova_screen1();
|
||||||
|
else if(key == '2') prova_screen2();
|
||||||
|
else if(key == 0x0d) break;
|
||||||
|
else woz_putc(key);
|
||||||
|
|
||||||
if(0) {
|
key = woz_getkey();
|
||||||
SCREEN1_INIT();
|
|
||||||
SCREEN1_FILL();
|
|
||||||
SCREEN1_LOAD_FONT();
|
|
||||||
|
|
||||||
SCREEN1_HOME(); SCREEN1_PUTS("*** P-LAB VIDEO CARD SYSTEM ***");
|
|
||||||
SCREEN1_LOCATEXY(0, 2); SCREEN1_PUTS("16K VRAM BYTES FREE");
|
|
||||||
SCREEN1_LOCATEXY(0, 4); SCREEN1_PUTS("READY.");
|
|
||||||
|
|
||||||
SCREEN1_LOCATEXY(0, 10);
|
|
||||||
for(i=0;i<256;i++) SCREEN1_PUTCHAR(i);
|
|
||||||
|
|
||||||
screen1_square_sprites();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1) {
|
|
||||||
SCREEN2_INIT();
|
|
||||||
SCREEN2_FILL();
|
|
||||||
screen2_square_sprites();
|
|
||||||
//SCREEN2_PUTC(65,1,1,0x1F);
|
|
||||||
|
|
||||||
SCREEN2_PUTS(0,0,0x1F,"*** P-LAB VIDEO CARD SYSTEM ***");
|
|
||||||
SCREEN2_PUTS(0,2,0x1F,"16K VRAM BYTES FREE");
|
|
||||||
SCREEN2_PUTS(0,4,0x1F,"READY.");
|
|
||||||
|
|
||||||
for(i=0;i<16;i++) {
|
|
||||||
SCREEN2_PUTS(5,6+i,((15-i)<<4)+i," COLOR ");
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<192;i++) {
|
|
||||||
SCREEN2_PSET(i,i/2);
|
|
||||||
SCREEN2_PSET(i,i);
|
|
||||||
SCREEN2_PSET(i/2,i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
woz_putc(42);
|
woz_putc(42);
|
||||||
woz_mon();
|
woz_mon();
|
||||||
}
|
}
|
||||||
|
|
854
test_apple1.asm
Normal file
854
test_apple1.asm
Normal file
|
@ -0,0 +1,854 @@
|
||||||
|
// TODO verificare NOPs
|
||||||
|
// Generic ASM 6502
|
||||||
|
.file [name="test.prg", type="prg", segments="Program"]
|
||||||
|
.segmentdef Program [segments="Code, Data"]
|
||||||
|
.segmentdef Code [start=$4000]
|
||||||
|
.segmentdef Data [startAfter="Code"]
|
||||||
|
.const WOZMON = $ff1f
|
||||||
|
// enters monitor
|
||||||
|
.const ECHO = $ffef
|
||||||
|
// print hex byte in A (A destroyed)
|
||||||
|
.const KEY_DATA = $d010
|
||||||
|
// read key
|
||||||
|
.const KEY_CTRL = $d011
|
||||||
|
// TMS9918 interface flags
|
||||||
|
.const WRITE_TO_REG = $80
|
||||||
|
.const WRITE_TO_VRAM = $40
|
||||||
|
// 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 SCREEN1_PATTERN_TABLE = $800
|
||||||
|
.const SCREEN1_NAME_TABLE = $1400
|
||||||
|
.const SCREEN1_COLOR_TABLE = $2000
|
||||||
|
.const SCREEN1_SPRITE_PATTERNS = 0
|
||||||
|
.const SCREEN1_SPRITE_ATTRS = $1000
|
||||||
|
.const SCREEN1_SIZE = $20*$18
|
||||||
|
// 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 SCREEN2_PATTERN_TABLE = 0
|
||||||
|
.const SCREEN2_NAME_TABLE = $3800
|
||||||
|
.const SCREEN2_COLOR_TABLE = $2000
|
||||||
|
.const SCREEN2_SPRITE_PATTERNS = $1800
|
||||||
|
.const SCREEN2_SPRITE_ATTRS = $3b00
|
||||||
|
.const SCREEN2_SIZE = $20*$18
|
||||||
|
// control port
|
||||||
|
.label VDP_DATA = $c000
|
||||||
|
// TMS9918 data port (VRAM)
|
||||||
|
.label VDP_REG = $c001
|
||||||
|
.label screen1_cursor = $d
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
lda #<0
|
||||||
|
sta.z screen1_cursor
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
ldx #'1'
|
||||||
|
__b1:
|
||||||
|
cpx #'1'
|
||||||
|
beq __b2
|
||||||
|
cpx #'2'
|
||||||
|
beq __b3
|
||||||
|
cpx #$d
|
||||||
|
beq __b4
|
||||||
|
stx.z woz_putc.c
|
||||||
|
jsr woz_putc
|
||||||
|
__b5:
|
||||||
|
jsr woz_getkey
|
||||||
|
tax
|
||||||
|
jmp __b1
|
||||||
|
__b4:
|
||||||
|
lda #$2a
|
||||||
|
sta.z woz_putc.c
|
||||||
|
jsr woz_putc
|
||||||
|
jsr woz_mon
|
||||||
|
rts
|
||||||
|
__b3:
|
||||||
|
jsr prova_screen2
|
||||||
|
jmp __b5
|
||||||
|
__b2:
|
||||||
|
jsr prova_screen1
|
||||||
|
jmp __b5
|
||||||
|
}
|
||||||
|
// puts a character on the apple1 screen using the WOZMON routine
|
||||||
|
// woz_putc(byte zp($11) c)
|
||||||
|
woz_putc: {
|
||||||
|
.label c = $11
|
||||||
|
lda c
|
||||||
|
jsr ECHO
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// reads a key from the apple-1 keyboard
|
||||||
|
woz_getkey: {
|
||||||
|
__b1:
|
||||||
|
lda KEY_CTRL
|
||||||
|
cmp #0
|
||||||
|
bne __b1
|
||||||
|
lda #$7f
|
||||||
|
and KEY_DATA
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// returns to WOZMON prompt
|
||||||
|
woz_mon: {
|
||||||
|
jmp WOZMON
|
||||||
|
}
|
||||||
|
prova_screen2: {
|
||||||
|
.label i = 2
|
||||||
|
.label i1 = 3
|
||||||
|
lda #<SCREEN2_TABLE
|
||||||
|
sta.z SCREEN_INIT.table
|
||||||
|
lda #>SCREEN2_TABLE
|
||||||
|
sta.z SCREEN_INIT.table+1
|
||||||
|
jsr SCREEN_INIT
|
||||||
|
jsr SCREEN2_FILL
|
||||||
|
jsr screen2_square_sprites
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #2
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s1
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s1
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #4
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s2
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s2
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #0
|
||||||
|
sta.z i
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
cmp #$10
|
||||||
|
bcc __b2
|
||||||
|
lda #0
|
||||||
|
sta.z i1
|
||||||
|
__b3:
|
||||||
|
lda.z i1
|
||||||
|
cmp #$c0
|
||||||
|
bcc __b4
|
||||||
|
rts
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
lsr
|
||||||
|
tax
|
||||||
|
lda.z i1
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
lda.z i1
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
ldx.z i1
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
lda.z i1
|
||||||
|
lsr
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
ldx.z i1
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
inc.z i1
|
||||||
|
jmp __b3
|
||||||
|
__b2:
|
||||||
|
lax.z i
|
||||||
|
axs #-[6]
|
||||||
|
stx.z SCREEN2_PUTS.y
|
||||||
|
lda #$f
|
||||||
|
sec
|
||||||
|
sbc.z i
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
clc
|
||||||
|
adc.z i
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #5
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s3
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s3
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
inc.z i
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
s3: .text " SCREEN 2 "
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
prova_screen1: {
|
||||||
|
.label i = 4
|
||||||
|
lda #<SCREEN1_TABLE
|
||||||
|
sta.z SCREEN_INIT.table
|
||||||
|
lda #>SCREEN1_TABLE
|
||||||
|
sta.z SCREEN_INIT.table+1
|
||||||
|
jsr SCREEN_INIT
|
||||||
|
jsr SCREEN1_FILL
|
||||||
|
jsr SCREEN1_LOAD_FONT
|
||||||
|
lda #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor
|
||||||
|
lda #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
lda #<s
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #2
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<s1
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s1
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #4
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<s2
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s2
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #$a
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i+1
|
||||||
|
cmp #>$100
|
||||||
|
bcc __b2
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp #<$100
|
||||||
|
bcc __b2
|
||||||
|
!:
|
||||||
|
jsr screen1_square_sprites
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
lda.z i
|
||||||
|
tay
|
||||||
|
jsr SCREEN1_PUTCHAR
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN_INIT(byte* zp($14) table)
|
||||||
|
SCREEN_INIT: {
|
||||||
|
.label table = $14
|
||||||
|
ldy #0
|
||||||
|
__b1:
|
||||||
|
cpy #8
|
||||||
|
bcc __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tya
|
||||||
|
tax
|
||||||
|
lda (table),y
|
||||||
|
jsr write_reg
|
||||||
|
iny
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
SCREEN2_FILL: {
|
||||||
|
.label i = 4
|
||||||
|
.label i1 = $14
|
||||||
|
.label i2 = 9
|
||||||
|
// fills name table x3 with increasing numbers
|
||||||
|
lda #<SCREEN2_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i+1
|
||||||
|
cmp #>SCREEN2_SIZE
|
||||||
|
bcc __b2
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp #<SCREEN2_SIZE
|
||||||
|
bcc __b2
|
||||||
|
!:
|
||||||
|
// fill pattern table with 0 (clear screen)
|
||||||
|
lda #<SCREEN2_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$300*8
|
||||||
|
sta.z i1
|
||||||
|
lda #>$300*8
|
||||||
|
sta.z i1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
ora.z i1+1
|
||||||
|
bne __b5
|
||||||
|
// fill color table with $1F
|
||||||
|
lda #<SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$300*8
|
||||||
|
sta.z i2
|
||||||
|
lda #>$300*8
|
||||||
|
sta.z i2+1
|
||||||
|
__b7:
|
||||||
|
lda.z i2
|
||||||
|
ora.z i2+1
|
||||||
|
bne __b8
|
||||||
|
rts
|
||||||
|
__b8:
|
||||||
|
lda #$1f
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i2
|
||||||
|
bne !+
|
||||||
|
dec.z i2+1
|
||||||
|
!:
|
||||||
|
dec.z i2
|
||||||
|
jmp __b7
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i1
|
||||||
|
bne !+
|
||||||
|
dec.z i1+1
|
||||||
|
!:
|
||||||
|
dec.z i1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$ff
|
||||||
|
and.z i
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
screen2_square_sprites: {
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
lda #<SCREEN2_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite patterns
|
||||||
|
__b1:
|
||||||
|
cpx #8
|
||||||
|
bcc __b2
|
||||||
|
// set sprite coordinates
|
||||||
|
lda #<SCREEN2_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite attribute
|
||||||
|
__b4:
|
||||||
|
cpx #$20
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
sta VDP_DATA
|
||||||
|
sta VDP_DATA
|
||||||
|
stx VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN2_PUTS(byte zp(8) x, byte zp(6) y, byte zp(7) col, byte* zp(9) s)
|
||||||
|
SCREEN2_PUTS: {
|
||||||
|
.label s = 9
|
||||||
|
.label x = 8
|
||||||
|
.label y = 6
|
||||||
|
.label col = 7
|
||||||
|
__b1:
|
||||||
|
ldy #0
|
||||||
|
lda (s),y
|
||||||
|
inc.z s
|
||||||
|
bne !+
|
||||||
|
inc.z s+1
|
||||||
|
!:
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tay
|
||||||
|
lda.z x
|
||||||
|
sta.z SCREEN2_PUTC.x
|
||||||
|
lda.z y
|
||||||
|
sta.z SCREEN2_PUTC.y
|
||||||
|
ldx.z col
|
||||||
|
jsr SCREEN2_PUTC
|
||||||
|
inc.z x
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN2_PSET(byte zp($12) x, byte register(X) y)
|
||||||
|
SCREEN2_PSET: {
|
||||||
|
.label __1 = $f
|
||||||
|
.label __3 = $14
|
||||||
|
.label __4 = $f
|
||||||
|
.label __12 = $14
|
||||||
|
.label paddr = $f
|
||||||
|
.label data = $13
|
||||||
|
.label x = $12
|
||||||
|
lda #$f8
|
||||||
|
and.z x
|
||||||
|
sta.z __1
|
||||||
|
lda #0
|
||||||
|
sta.z __1+1
|
||||||
|
txa
|
||||||
|
and #$f8
|
||||||
|
sta.z __12
|
||||||
|
lda #0
|
||||||
|
sta.z __12+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
lda.z __4
|
||||||
|
clc
|
||||||
|
adc.z __3
|
||||||
|
sta.z __4
|
||||||
|
lda.z __4+1
|
||||||
|
adc.z __3+1
|
||||||
|
sta.z __4+1
|
||||||
|
txa
|
||||||
|
and #8-1
|
||||||
|
clc
|
||||||
|
adc.z paddr
|
||||||
|
sta.z paddr
|
||||||
|
bcc !+
|
||||||
|
inc.z paddr+1
|
||||||
|
!:
|
||||||
|
lda.z paddr
|
||||||
|
sta.z set_vram_read_addr.addr
|
||||||
|
lda.z paddr+1
|
||||||
|
sta.z set_vram_read_addr.addr+1
|
||||||
|
jsr set_vram_read_addr
|
||||||
|
lda VDP_DATA
|
||||||
|
sta.z data
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #8-1
|
||||||
|
and.z x
|
||||||
|
tay
|
||||||
|
lda pow2_table,y
|
||||||
|
ora.z data
|
||||||
|
sta VDP_DATA
|
||||||
|
rts
|
||||||
|
.segment Data
|
||||||
|
pow2_table: .byte $80, $40, $20, $10, 8, 4, 2, 1
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
SCREEN1_FILL: {
|
||||||
|
.label i = $14
|
||||||
|
.label i1 = 9
|
||||||
|
// fills name table with spaces (32)
|
||||||
|
lda #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<SCREEN1_SIZE
|
||||||
|
sta.z i
|
||||||
|
lda #>SCREEN1_SIZE
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
ora.z i+1
|
||||||
|
bne __b2
|
||||||
|
// fill pattern table with 0
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$100*8
|
||||||
|
sta.z i1
|
||||||
|
lda #>$100*8
|
||||||
|
sta.z i1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
ora.z i1+1
|
||||||
|
bne __b5
|
||||||
|
// fill color table with $1F
|
||||||
|
lda #<SCREEN1_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #$20
|
||||||
|
__b7:
|
||||||
|
cpx #0
|
||||||
|
bne __b8
|
||||||
|
rts
|
||||||
|
__b8:
|
||||||
|
lda #$1f
|
||||||
|
sta VDP_DATA
|
||||||
|
dex
|
||||||
|
jmp __b7
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i1
|
||||||
|
bne !+
|
||||||
|
dec.z i1+1
|
||||||
|
!:
|
||||||
|
dec.z i1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$20
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i
|
||||||
|
bne !+
|
||||||
|
dec.z i+1
|
||||||
|
!:
|
||||||
|
dec.z i
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// loads the Laser 500 font on the pattern table
|
||||||
|
SCREEN1_LOAD_FONT: {
|
||||||
|
// reverse font (32..127)
|
||||||
|
.label source = 9
|
||||||
|
.label i = $14
|
||||||
|
// reverse font (32..127)
|
||||||
|
.label source_1 = $d
|
||||||
|
.label i_1 = $b
|
||||||
|
// start writing into VRAM from space character (32..127)
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE+$20*8
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE+$20*8
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<FONT
|
||||||
|
sta.z source
|
||||||
|
lda #>FONT
|
||||||
|
sta.z source+1
|
||||||
|
lda #<$300
|
||||||
|
sta.z i
|
||||||
|
lda #>$300
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
ora.z i+1
|
||||||
|
bne __b2
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE+($80+$20)*8
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE+($80+$20)*8
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<FONT
|
||||||
|
sta.z source_1
|
||||||
|
lda #>FONT
|
||||||
|
sta.z source_1+1
|
||||||
|
lda #<$300
|
||||||
|
sta.z i_1
|
||||||
|
lda #>$300
|
||||||
|
sta.z i_1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i_1
|
||||||
|
ora.z i_1+1
|
||||||
|
bne __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
ldy #0
|
||||||
|
lda (source_1),y
|
||||||
|
eor #$ff
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z source_1
|
||||||
|
bne !+
|
||||||
|
inc.z source_1+1
|
||||||
|
!:
|
||||||
|
lda.z i_1
|
||||||
|
bne !+
|
||||||
|
dec.z i_1+1
|
||||||
|
!:
|
||||||
|
dec.z i_1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
ldy #0
|
||||||
|
lda (source),y
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z source
|
||||||
|
bne !+
|
||||||
|
inc.z source+1
|
||||||
|
!:
|
||||||
|
lda.z i
|
||||||
|
bne !+
|
||||||
|
dec.z i+1
|
||||||
|
!:
|
||||||
|
dec.z i
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// prints 0 terminated string pointed by YA
|
||||||
|
// SCREEN1_PUTS(byte* zp($b) s)
|
||||||
|
SCREEN1_PUTS: {
|
||||||
|
.label s = $b
|
||||||
|
__b1:
|
||||||
|
ldy #0
|
||||||
|
lda (s),y
|
||||||
|
inc.z s
|
||||||
|
bne !+
|
||||||
|
inc.z s+1
|
||||||
|
!:
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tay
|
||||||
|
jsr SCREEN1_PUTCHAR
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN1_LOCATEXY(byte register(A) y)
|
||||||
|
SCREEN1_LOCATEXY: {
|
||||||
|
.label __0 = $d
|
||||||
|
.label __3 = $d
|
||||||
|
sta.z __3
|
||||||
|
lda #0
|
||||||
|
sta.z __3+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
clc
|
||||||
|
lda.z screen1_cursor
|
||||||
|
adc #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor
|
||||||
|
lda.z screen1_cursor+1
|
||||||
|
adc #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
screen1_square_sprites: {
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
lda #<SCREEN1_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite patterns
|
||||||
|
__b1:
|
||||||
|
cpx #8
|
||||||
|
bcc __b2
|
||||||
|
// set sprite coordinates
|
||||||
|
lda #<SCREEN1_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
// start writing in the sprite attribute
|
||||||
|
__b4:
|
||||||
|
cpy #$20
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc #6
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
sta VDP_DATA
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc #6
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
sta VDP_DATA
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
sty VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$ff
|
||||||
|
sta VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// prints character to TMS (SCREEN 1 MODE)
|
||||||
|
// SCREEN1_PUTCHAR(byte register(Y) c)
|
||||||
|
SCREEN1_PUTCHAR: {
|
||||||
|
lda.z screen1_cursor
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z screen1_cursor+1
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
inc.z screen1_cursor
|
||||||
|
bne !+
|
||||||
|
inc.z screen1_cursor+1
|
||||||
|
!:
|
||||||
|
sty VDP_DATA
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// writes a value to a TMS9918 register (0-7)
|
||||||
|
// write_reg(byte register(X) regnum, byte register(A) val)
|
||||||
|
write_reg: {
|
||||||
|
sta VDP_REG
|
||||||
|
txa
|
||||||
|
and #$f
|
||||||
|
ora #WRITE_TO_REG
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// sets the VRAM write address on the TMS9918
|
||||||
|
// set_vram_write_addr(word zp($f) addr)
|
||||||
|
set_vram_write_addr: {
|
||||||
|
.label addr = $f
|
||||||
|
lda.z addr
|
||||||
|
sta VDP_REG
|
||||||
|
lda.z addr+1
|
||||||
|
and #$3f
|
||||||
|
ora #WRITE_TO_VRAM
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// SCREEN2_PUTC(byte register(Y) ch, byte zp($12) x, byte zp($13) y, byte register(X) col)
|
||||||
|
SCREEN2_PUTC: {
|
||||||
|
.label __1 = $14
|
||||||
|
.label __4 = $16
|
||||||
|
.label __12 = $14
|
||||||
|
.label source = $14
|
||||||
|
.label addr = $16
|
||||||
|
.label x = $12
|
||||||
|
.label y = $13
|
||||||
|
tya
|
||||||
|
sec
|
||||||
|
sbc #$20
|
||||||
|
sta.z __12
|
||||||
|
lda #0
|
||||||
|
sta.z __12+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
clc
|
||||||
|
lda.z source
|
||||||
|
adc #<FONT
|
||||||
|
sta.z source
|
||||||
|
lda.z source+1
|
||||||
|
adc #>FONT
|
||||||
|
sta.z source+1
|
||||||
|
lda.z x
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
tay
|
||||||
|
lda.z y
|
||||||
|
sta.z __4+1
|
||||||
|
lda #0
|
||||||
|
sta.z __4
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc.z addr
|
||||||
|
sta.z addr
|
||||||
|
bcc !+
|
||||||
|
inc.z addr+1
|
||||||
|
!:
|
||||||
|
lda.z addr
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z addr+1
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
__b1:
|
||||||
|
cpy #8
|
||||||
|
bcc __b2
|
||||||
|
clc
|
||||||
|
lda.z addr
|
||||||
|
adc #<SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z addr+1
|
||||||
|
adc #>SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
__b4:
|
||||||
|
cpy #8
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
stx VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda (source),y
|
||||||
|
sta VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// sets the VRAM read address on the TMS9918
|
||||||
|
// set_vram_read_addr(word zp($16) addr)
|
||||||
|
set_vram_read_addr: {
|
||||||
|
.label addr = $16
|
||||||
|
lda.z addr
|
||||||
|
sta VDP_REG
|
||||||
|
lda.z addr+1
|
||||||
|
and #$3f
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
.segment Data
|
||||||
|
FONT: .byte 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 8, 0, $14, $14, $14, 0, 0, 0, 0, 0, $14, $14, $3e, $14, $3e, $14, $14, 0, 8, $1e, $28, $1c, $a, $3c, 8, 0, $30, $32, 4, 8, $10, $26, 6, 0, $10, $28, $28, $10, $2a, $24, $1a, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, $10, $20, $20, $20, $10, 8, 0, 8, 4, 2, 2, 2, 4, 8, 0, 8, $2a, $1c, 8, $1c, $2a, 8, 0, 0, 8, 8, $3e, 8, 8, 0, 0, 0, 0, 0, 0, 8, 8, $10, 0, 0, 0, 0, $3e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 2, 4, 8, $10, $20, 0, 0, $1c, $22, $26, $2a, $32, $22, $1c, 0, 8, $18, 8, 8, 8, 8, $1c, 0, $1c, $22, 2, $c, $10, $20, $3e, 0, $3e, 2, 4, $c, 2, $22, $1c, 0, 4, $c, $14, $24, $3e, 4, 4, 0, $3e, $20, $3c, 2, 2, $22, $1c, 0, $e, $10, $20, $3c, $22, $22, $1c, 0, $3e, 2, 4, 8, $10, $20, $20, 0, $1c, $22, $22, $1c, $22, $22, $1c, 0, $1c, $22, $22, $1e, 2, 4, $38, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 8, $10, 0, 4, 8, $10, $20, $10, 8, 4, 0, 0, 0, $3e, 0, $3e, 0, 0, 0, $10, 8, 4, 2, 4, 8, $10, 0, $1c, $22, 4, 8, 8, 0, 8, 0, $1c, $22, $2a, $2e, $2c, $20, $1c, 0, 8, $14, $22, $22, $3e, $22, $22, 0, $3c, $22, $22, $3c, $22, $22, $3c, 0, $1c, $22, $20, $20, $20, $22, $1c, 0, $38, $24, $22, $22, $22, $24, $38, 0, $3e, $20, $20, $38, $20, $20, $3e, 0, $3e, $20, $20, $38, $20, $20, $20, 0, $1e, $20, $20, $20, $26, $22, $1e, 0, $22, $22, $22, $3e, $22, $22, $22, 0, $1c, 8, 8, 8, 8, 8, $1c, 0, 2, 2, 2, 2, 2, $22, $1c, 0, $22, $24, $28, $30, $28, $24, $22, 0, $20, $20, $20, $20, $20, $20, $3e, 0, $22, $36, $2a, $2a, $22, $22, $22, 0, $22, $22, $32, $2a, $26, $22, $22, 0, $1c, $22, $22, $22, $22, $22, $1c, 0, $3c, $22, $22, $3c, $20, $20, $20, 0, $1c, $22, $22, $22, $2a, $24, $1a, 0, $3c, $22, $22, $3c, $28, $24, $22, 0, $1c, $22, $20, $1c, 2, $22, $1c, 0, $3e, 8, 8, 8, 8, 8, 8, 0, $22, $22, $22, $22, $22, $22, $1c, 0, $22, $22, $22, $22, $22, $14, 8, 0, $22, $22, $22, $2a, $2a, $36, $22, 0, $22, $22, $14, 8, $14, $22, $22, 0, $22, $22, $14, 8, 8, 8, 8, 0, $3e, 2, 4, 8, $10, $20, $3e, 0, $3e, $30, $30, $30, $30, $30, $3e, 0, 0, $20, $10, 8, 4, 2, 0, 0, $3e, 6, 6, 6, 6, 6, $3e, 0, 8, $14, $22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, $3e, $10, 8, 4, 0, 0, 0, 0, 0, 0, 0, $1c, 2, $1e, $22, $1e, 0, $20, $20, $3c, $22, $22, $22, $3c, 0, 0, 0, $1e, $20, $20, $20, $1e, 0, 2, 2, $1e, $22, $22, $22, $1e, 0, 0, 0, $1c, $22, $3e, $20, $1e, 0, $c, $12, $10, $3c, $10, $10, $10, 0, 0, 0, $1c, $22, $22, $1e, 2, $1c, $20, $20, $3c, $22, $22, $22, $22, 0, 8, 0, $18, 8, 8, 8, $1c, 0, 2, 0, 6, 2, 2, 2, $12, $c, $20, $20, $22, $24, $38, $24, $22, 0, $18, 8, 8, 8, 8, 8, $1c, 0, 0, 0, $34, $2a, $2a, $2a, $22, 0, 0, 0, $3c, $22, $22, $22, $22, 0, 0, 0, $1c, $22, $22, $22, $1c, 0, 0, 0, $3c, $22, $22, $3c, $20, $20, 0, 0, $1e, $22, $22, $1e, 2, 2, 0, 0, $2e, $30, $20, $20, $20, 0, 0, 0, $1e, $20, $1c, 2, $3c, 0, $10, $10, $3c, $10, $10, $12, $c, 0, 0, 0, $22, $22, $22, $26, $1a, 0, 0, 0, $22, $22, $22, $14, 8, 0, 0, 0, $22, $22, $2a, $2a, $14, 0, 0, 0, $22, $14, 8, $14, $22, 0, 0, 0, $22, $24, $14, $18, 8, $30, 0, 0, $3e, 4, 8, $10, $3e, 0, 6, 8, 8, $30, 8, 8, 6, 0, 8, 8, 8, 8, 8, 8, 8, 8, $30, 8, 8, 6, 8, 8, $30, 0, $1a, $2c, 0, 0, 0, 0, 0, 0
|
||||||
|
.fill 8, 0
|
||||||
|
SCREEN1_TABLE: .byte 0, $c0, 5, $80, 1, $20, 0, $25
|
||||||
|
SCREEN2_TABLE: .byte 2, $c0, $e, $ff, 3, $76, 3, $25
|
||||||
|
s: .text "*** P-LAB VIDEO CARD SYSTEM ***"
|
||||||
|
.byte 0
|
||||||
|
s1: .text "16K VRAM BYTES FREE"
|
||||||
|
.byte 0
|
||||||
|
s2: .text "READY."
|
||||||
|
.byte 0
|
853
test_vic20.asm
Normal file
853
test_vic20.asm
Normal file
|
@ -0,0 +1,853 @@
|
||||||
|
// TODO verificare NOPs
|
||||||
|
// Commodore VIC 20 executable PRG file
|
||||||
|
.file [name="test.prg", type="prg", segments="Program"]
|
||||||
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
|
.segmentdef Basic [start=$1001]
|
||||||
|
.segmentdef Code [start=$100d]
|
||||||
|
.segmentdef Data [startAfter="Code"]
|
||||||
|
.segment Basic
|
||||||
|
:BasicUpstart(main)
|
||||||
|
// VIC20
|
||||||
|
.const ECHO = $ffd2
|
||||||
|
// chrout routine in kernal rom
|
||||||
|
.const GETIN = $ffe4
|
||||||
|
// TMS9918 interface flags
|
||||||
|
.const WRITE_TO_REG = $80
|
||||||
|
.const WRITE_TO_VRAM = $40
|
||||||
|
// 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 SCREEN1_PATTERN_TABLE = $800
|
||||||
|
.const SCREEN1_NAME_TABLE = $1400
|
||||||
|
.const SCREEN1_COLOR_TABLE = $2000
|
||||||
|
.const SCREEN1_SPRITE_PATTERNS = 0
|
||||||
|
.const SCREEN1_SPRITE_ATTRS = $1000
|
||||||
|
.const SCREEN1_SIZE = $20*$18
|
||||||
|
// 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 SCREEN2_PATTERN_TABLE = 0
|
||||||
|
.const SCREEN2_NAME_TABLE = $3800
|
||||||
|
.const SCREEN2_COLOR_TABLE = $2000
|
||||||
|
.const SCREEN2_SPRITE_PATTERNS = $1800
|
||||||
|
.const SCREEN2_SPRITE_ATTRS = $3b00
|
||||||
|
.const SCREEN2_SIZE = $20*$18
|
||||||
|
// GETIN keyboard read routine
|
||||||
|
.label VDP_DATA = $a000
|
||||||
|
// TMS9918 data port (VRAM)
|
||||||
|
.label VDP_REG = $a001
|
||||||
|
.label screen1_cursor = $d
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
lda #<0
|
||||||
|
sta.z screen1_cursor
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
ldx #'1'
|
||||||
|
__b1:
|
||||||
|
cpx #'1'
|
||||||
|
beq __b2
|
||||||
|
cpx #'2'
|
||||||
|
beq __b3
|
||||||
|
cpx #$d
|
||||||
|
beq __b4
|
||||||
|
stx.z woz_putc.c
|
||||||
|
jsr woz_putc
|
||||||
|
__b5:
|
||||||
|
jsr woz_getkey
|
||||||
|
tax
|
||||||
|
jmp __b1
|
||||||
|
__b4:
|
||||||
|
lda #$2a
|
||||||
|
sta.z woz_putc.c
|
||||||
|
jsr woz_putc
|
||||||
|
rts
|
||||||
|
__b3:
|
||||||
|
jsr prova_screen2
|
||||||
|
jmp __b5
|
||||||
|
__b2:
|
||||||
|
jsr prova_screen1
|
||||||
|
jmp __b5
|
||||||
|
}
|
||||||
|
// puts a character on the apple1 screen using the WOZMON routine
|
||||||
|
// woz_putc(byte zp($11) c)
|
||||||
|
woz_putc: {
|
||||||
|
.label c = $11
|
||||||
|
lda c
|
||||||
|
jsr ECHO
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// reads a key from the apple-1 keyboard
|
||||||
|
woz_getkey: {
|
||||||
|
.label keyptr = key
|
||||||
|
.label key = $12
|
||||||
|
lda #0
|
||||||
|
sta.z key
|
||||||
|
__wait:
|
||||||
|
jsr GETIN
|
||||||
|
cmp #0
|
||||||
|
beq __wait
|
||||||
|
sta keyptr
|
||||||
|
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
prova_screen2: {
|
||||||
|
.label i = 2
|
||||||
|
.label i1 = 3
|
||||||
|
lda #<SCREEN2_TABLE
|
||||||
|
sta.z SCREEN_INIT.table
|
||||||
|
lda #>SCREEN2_TABLE
|
||||||
|
sta.z SCREEN_INIT.table+1
|
||||||
|
jsr SCREEN_INIT
|
||||||
|
jsr SCREEN2_FILL
|
||||||
|
jsr screen2_square_sprites
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #2
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s1
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s1
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #$1f
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #4
|
||||||
|
sta.z SCREEN2_PUTS.y
|
||||||
|
lda #0
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s2
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s2
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
lda #0
|
||||||
|
sta.z i
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
cmp #$10
|
||||||
|
bcc __b2
|
||||||
|
lda #0
|
||||||
|
sta.z i1
|
||||||
|
__b3:
|
||||||
|
lda.z i1
|
||||||
|
cmp #$c0
|
||||||
|
bcc __b4
|
||||||
|
rts
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
lsr
|
||||||
|
tax
|
||||||
|
lda.z i1
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
lda.z i1
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
ldx.z i1
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
lda.z i1
|
||||||
|
lsr
|
||||||
|
sta.z SCREEN2_PSET.x
|
||||||
|
ldx.z i1
|
||||||
|
jsr SCREEN2_PSET
|
||||||
|
inc.z i1
|
||||||
|
jmp __b3
|
||||||
|
__b2:
|
||||||
|
lax.z i
|
||||||
|
axs #-[6]
|
||||||
|
stx.z SCREEN2_PUTS.y
|
||||||
|
lda #$f
|
||||||
|
sec
|
||||||
|
sbc.z i
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
clc
|
||||||
|
adc.z i
|
||||||
|
sta.z SCREEN2_PUTS.col
|
||||||
|
lda #5
|
||||||
|
sta.z SCREEN2_PUTS.x
|
||||||
|
lda #<s3
|
||||||
|
sta.z SCREEN2_PUTS.s
|
||||||
|
lda #>s3
|
||||||
|
sta.z SCREEN2_PUTS.s+1
|
||||||
|
jsr SCREEN2_PUTS
|
||||||
|
inc.z i
|
||||||
|
jmp __b1
|
||||||
|
.segment Data
|
||||||
|
s3: .text " SCREEN 2 "
|
||||||
|
.byte 0
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
prova_screen1: {
|
||||||
|
.label i = 4
|
||||||
|
lda #<SCREEN1_TABLE
|
||||||
|
sta.z SCREEN_INIT.table
|
||||||
|
lda #>SCREEN1_TABLE
|
||||||
|
sta.z SCREEN_INIT.table+1
|
||||||
|
jsr SCREEN_INIT
|
||||||
|
jsr SCREEN1_FILL
|
||||||
|
jsr SCREEN1_LOAD_FONT
|
||||||
|
lda #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor
|
||||||
|
lda #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
lda #<s
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #2
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<s1
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s1
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #4
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<s2
|
||||||
|
sta.z SCREEN1_PUTS.s
|
||||||
|
lda #>s2
|
||||||
|
sta.z SCREEN1_PUTS.s+1
|
||||||
|
jsr SCREEN1_PUTS
|
||||||
|
lda #$a
|
||||||
|
jsr SCREEN1_LOCATEXY
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i+1
|
||||||
|
cmp #>$100
|
||||||
|
bcc __b2
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp #<$100
|
||||||
|
bcc __b2
|
||||||
|
!:
|
||||||
|
jsr screen1_square_sprites
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
lda.z i
|
||||||
|
tay
|
||||||
|
jsr SCREEN1_PUTCHAR
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN_INIT(byte* zp($15) table)
|
||||||
|
SCREEN_INIT: {
|
||||||
|
.label table = $15
|
||||||
|
ldy #0
|
||||||
|
__b1:
|
||||||
|
cpy #8
|
||||||
|
bcc __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tya
|
||||||
|
tax
|
||||||
|
lda (table),y
|
||||||
|
jsr write_reg
|
||||||
|
iny
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
SCREEN2_FILL: {
|
||||||
|
.label i = 4
|
||||||
|
.label i1 = $15
|
||||||
|
.label i2 = 9
|
||||||
|
// fills name table x3 with increasing numbers
|
||||||
|
lda #<SCREEN2_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<0
|
||||||
|
sta.z i
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i+1
|
||||||
|
cmp #>SCREEN2_SIZE
|
||||||
|
bcc __b2
|
||||||
|
bne !+
|
||||||
|
lda.z i
|
||||||
|
cmp #<SCREEN2_SIZE
|
||||||
|
bcc __b2
|
||||||
|
!:
|
||||||
|
// fill pattern table with 0 (clear screen)
|
||||||
|
lda #<SCREEN2_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$300*8
|
||||||
|
sta.z i1
|
||||||
|
lda #>$300*8
|
||||||
|
sta.z i1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
ora.z i1+1
|
||||||
|
bne __b5
|
||||||
|
// fill color table with $1F
|
||||||
|
lda #<SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$300*8
|
||||||
|
sta.z i2
|
||||||
|
lda #>$300*8
|
||||||
|
sta.z i2+1
|
||||||
|
__b7:
|
||||||
|
lda.z i2
|
||||||
|
ora.z i2+1
|
||||||
|
bne __b8
|
||||||
|
rts
|
||||||
|
__b8:
|
||||||
|
lda #$1f
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i2
|
||||||
|
bne !+
|
||||||
|
dec.z i2+1
|
||||||
|
!:
|
||||||
|
dec.z i2
|
||||||
|
jmp __b7
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i1
|
||||||
|
bne !+
|
||||||
|
dec.z i1+1
|
||||||
|
!:
|
||||||
|
dec.z i1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$ff
|
||||||
|
and.z i
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z i
|
||||||
|
bne !+
|
||||||
|
inc.z i+1
|
||||||
|
!:
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
screen2_square_sprites: {
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
lda #<SCREEN2_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite patterns
|
||||||
|
__b1:
|
||||||
|
cpx #8
|
||||||
|
bcc __b2
|
||||||
|
// set sprite coordinates
|
||||||
|
lda #<SCREEN2_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN2_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite attribute
|
||||||
|
__b4:
|
||||||
|
cpx #$20
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
sta VDP_DATA
|
||||||
|
sta VDP_DATA
|
||||||
|
stx VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN2_PUTS(byte zp(8) x, byte zp(6) y, byte zp(7) col, byte* zp(9) s)
|
||||||
|
SCREEN2_PUTS: {
|
||||||
|
.label s = 9
|
||||||
|
.label x = 8
|
||||||
|
.label y = 6
|
||||||
|
.label col = 7
|
||||||
|
__b1:
|
||||||
|
ldy #0
|
||||||
|
lda (s),y
|
||||||
|
inc.z s
|
||||||
|
bne !+
|
||||||
|
inc.z s+1
|
||||||
|
!:
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tay
|
||||||
|
lda.z x
|
||||||
|
sta.z SCREEN2_PUTC.x
|
||||||
|
lda.z y
|
||||||
|
sta.z SCREEN2_PUTC.y
|
||||||
|
ldx.z col
|
||||||
|
jsr SCREEN2_PUTC
|
||||||
|
inc.z x
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN2_PSET(byte zp($13) x, byte register(X) y)
|
||||||
|
SCREEN2_PSET: {
|
||||||
|
.label __1 = $f
|
||||||
|
.label __3 = $15
|
||||||
|
.label __4 = $f
|
||||||
|
.label __12 = $15
|
||||||
|
.label paddr = $f
|
||||||
|
.label data = $14
|
||||||
|
.label x = $13
|
||||||
|
lda #$f8
|
||||||
|
and.z x
|
||||||
|
sta.z __1
|
||||||
|
lda #0
|
||||||
|
sta.z __1+1
|
||||||
|
txa
|
||||||
|
and #$f8
|
||||||
|
sta.z __12
|
||||||
|
lda #0
|
||||||
|
sta.z __12+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
asl.z __3
|
||||||
|
rol.z __3+1
|
||||||
|
lda.z __4
|
||||||
|
clc
|
||||||
|
adc.z __3
|
||||||
|
sta.z __4
|
||||||
|
lda.z __4+1
|
||||||
|
adc.z __3+1
|
||||||
|
sta.z __4+1
|
||||||
|
txa
|
||||||
|
and #8-1
|
||||||
|
clc
|
||||||
|
adc.z paddr
|
||||||
|
sta.z paddr
|
||||||
|
bcc !+
|
||||||
|
inc.z paddr+1
|
||||||
|
!:
|
||||||
|
lda.z paddr
|
||||||
|
sta.z set_vram_read_addr.addr
|
||||||
|
lda.z paddr+1
|
||||||
|
sta.z set_vram_read_addr.addr+1
|
||||||
|
jsr set_vram_read_addr
|
||||||
|
lda VDP_DATA
|
||||||
|
sta.z data
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #8-1
|
||||||
|
and.z x
|
||||||
|
tay
|
||||||
|
lda pow2_table,y
|
||||||
|
ora.z data
|
||||||
|
sta VDP_DATA
|
||||||
|
rts
|
||||||
|
.segment Data
|
||||||
|
pow2_table: .byte $80, $40, $20, $10, 8, 4, 2, 1
|
||||||
|
}
|
||||||
|
.segment Code
|
||||||
|
SCREEN1_FILL: {
|
||||||
|
.label i = $15
|
||||||
|
.label i1 = 9
|
||||||
|
// fills name table with spaces (32)
|
||||||
|
lda #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<SCREEN1_SIZE
|
||||||
|
sta.z i
|
||||||
|
lda #>SCREEN1_SIZE
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
ora.z i+1
|
||||||
|
bne __b2
|
||||||
|
// fill pattern table with 0
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<$100*8
|
||||||
|
sta.z i1
|
||||||
|
lda #>$100*8
|
||||||
|
sta.z i1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i1
|
||||||
|
ora.z i1+1
|
||||||
|
bne __b5
|
||||||
|
// fill color table with $1F
|
||||||
|
lda #<SCREEN1_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #$20
|
||||||
|
__b7:
|
||||||
|
cpx #0
|
||||||
|
bne __b8
|
||||||
|
rts
|
||||||
|
__b8:
|
||||||
|
lda #$1f
|
||||||
|
sta VDP_DATA
|
||||||
|
dex
|
||||||
|
jmp __b7
|
||||||
|
__b5:
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i1
|
||||||
|
bne !+
|
||||||
|
dec.z i1+1
|
||||||
|
!:
|
||||||
|
dec.z i1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$20
|
||||||
|
sta VDP_DATA
|
||||||
|
lda.z i
|
||||||
|
bne !+
|
||||||
|
dec.z i+1
|
||||||
|
!:
|
||||||
|
dec.z i
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// loads the Laser 500 font on the pattern table
|
||||||
|
SCREEN1_LOAD_FONT: {
|
||||||
|
// reverse font (32..127)
|
||||||
|
.label source = 9
|
||||||
|
.label i = $15
|
||||||
|
// reverse font (32..127)
|
||||||
|
.label source_1 = $d
|
||||||
|
.label i_1 = $b
|
||||||
|
// start writing into VRAM from space character (32..127)
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE+$20*8
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE+$20*8
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<FONT
|
||||||
|
sta.z source
|
||||||
|
lda #>FONT
|
||||||
|
sta.z source+1
|
||||||
|
lda #<$300
|
||||||
|
sta.z i
|
||||||
|
lda #>$300
|
||||||
|
sta.z i+1
|
||||||
|
__b1:
|
||||||
|
lda.z i
|
||||||
|
ora.z i+1
|
||||||
|
bne __b2
|
||||||
|
lda #<SCREEN1_PATTERN_TABLE+($80+$20)*8
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_PATTERN_TABLE+($80+$20)*8
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
lda #<FONT
|
||||||
|
sta.z source_1
|
||||||
|
lda #>FONT
|
||||||
|
sta.z source_1+1
|
||||||
|
lda #<$300
|
||||||
|
sta.z i_1
|
||||||
|
lda #>$300
|
||||||
|
sta.z i_1+1
|
||||||
|
__b4:
|
||||||
|
lda.z i_1
|
||||||
|
ora.z i_1+1
|
||||||
|
bne __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
ldy #0
|
||||||
|
lda (source_1),y
|
||||||
|
eor #$ff
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z source_1
|
||||||
|
bne !+
|
||||||
|
inc.z source_1+1
|
||||||
|
!:
|
||||||
|
lda.z i_1
|
||||||
|
bne !+
|
||||||
|
dec.z i_1+1
|
||||||
|
!:
|
||||||
|
dec.z i_1
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
ldy #0
|
||||||
|
lda (source),y
|
||||||
|
sta VDP_DATA
|
||||||
|
inc.z source
|
||||||
|
bne !+
|
||||||
|
inc.z source+1
|
||||||
|
!:
|
||||||
|
lda.z i
|
||||||
|
bne !+
|
||||||
|
dec.z i+1
|
||||||
|
!:
|
||||||
|
dec.z i
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// prints 0 terminated string pointed by YA
|
||||||
|
// SCREEN1_PUTS(byte* zp($b) s)
|
||||||
|
SCREEN1_PUTS: {
|
||||||
|
.label s = $b
|
||||||
|
__b1:
|
||||||
|
ldy #0
|
||||||
|
lda (s),y
|
||||||
|
inc.z s
|
||||||
|
bne !+
|
||||||
|
inc.z s+1
|
||||||
|
!:
|
||||||
|
cmp #0
|
||||||
|
bne __b2
|
||||||
|
rts
|
||||||
|
__b2:
|
||||||
|
tay
|
||||||
|
jsr SCREEN1_PUTCHAR
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// SCREEN1_LOCATEXY(byte register(A) y)
|
||||||
|
SCREEN1_LOCATEXY: {
|
||||||
|
.label __0 = $d
|
||||||
|
.label __3 = $d
|
||||||
|
sta.z __3
|
||||||
|
lda #0
|
||||||
|
sta.z __3+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
asl.z __0
|
||||||
|
rol.z __0+1
|
||||||
|
clc
|
||||||
|
lda.z screen1_cursor
|
||||||
|
adc #<SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor
|
||||||
|
lda.z screen1_cursor+1
|
||||||
|
adc #>SCREEN1_NAME_TABLE
|
||||||
|
sta.z screen1_cursor+1
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
screen1_square_sprites: {
|
||||||
|
// fills first sprite pattern with 255
|
||||||
|
lda #<SCREEN1_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_SPRITE_PATTERNS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldx #0
|
||||||
|
// start writing in the sprite patterns
|
||||||
|
__b1:
|
||||||
|
cpx #8
|
||||||
|
bcc __b2
|
||||||
|
// set sprite coordinates
|
||||||
|
lda #<SCREEN1_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda #>SCREEN1_SPRITE_ATTRS
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
// start writing in the sprite attribute
|
||||||
|
__b4:
|
||||||
|
cpy #$20
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc #6
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
sta VDP_DATA
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc #6
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
sta VDP_DATA
|
||||||
|
lda #0
|
||||||
|
sta VDP_DATA
|
||||||
|
sty VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda #$ff
|
||||||
|
sta VDP_DATA
|
||||||
|
inx
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// prints character to TMS (SCREEN 1 MODE)
|
||||||
|
// SCREEN1_PUTCHAR(byte register(Y) c)
|
||||||
|
SCREEN1_PUTCHAR: {
|
||||||
|
lda.z screen1_cursor
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z screen1_cursor+1
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
inc.z screen1_cursor
|
||||||
|
bne !+
|
||||||
|
inc.z screen1_cursor+1
|
||||||
|
!:
|
||||||
|
sty VDP_DATA
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// writes a value to a TMS9918 register (0-7)
|
||||||
|
// write_reg(byte register(X) regnum, byte register(A) val)
|
||||||
|
write_reg: {
|
||||||
|
sta VDP_REG
|
||||||
|
txa
|
||||||
|
and #$f
|
||||||
|
ora #WRITE_TO_REG
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// sets the VRAM write address on the TMS9918
|
||||||
|
// set_vram_write_addr(word zp($f) addr)
|
||||||
|
set_vram_write_addr: {
|
||||||
|
.label addr = $f
|
||||||
|
lda.z addr
|
||||||
|
sta VDP_REG
|
||||||
|
lda.z addr+1
|
||||||
|
and #$3f
|
||||||
|
ora #WRITE_TO_VRAM
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// SCREEN2_PUTC(byte register(Y) ch, byte zp($13) x, byte zp($14) y, byte register(X) col)
|
||||||
|
SCREEN2_PUTC: {
|
||||||
|
.label __1 = $15
|
||||||
|
.label __4 = $17
|
||||||
|
.label __12 = $15
|
||||||
|
.label source = $15
|
||||||
|
.label addr = $17
|
||||||
|
.label x = $13
|
||||||
|
.label y = $14
|
||||||
|
tya
|
||||||
|
sec
|
||||||
|
sbc #$20
|
||||||
|
sta.z __12
|
||||||
|
lda #0
|
||||||
|
sta.z __12+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
asl.z __1
|
||||||
|
rol.z __1+1
|
||||||
|
clc
|
||||||
|
lda.z source
|
||||||
|
adc #<FONT
|
||||||
|
sta.z source
|
||||||
|
lda.z source+1
|
||||||
|
adc #>FONT
|
||||||
|
sta.z source+1
|
||||||
|
lda.z x
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
tay
|
||||||
|
lda.z y
|
||||||
|
sta.z __4+1
|
||||||
|
lda #0
|
||||||
|
sta.z __4
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc.z addr
|
||||||
|
sta.z addr
|
||||||
|
bcc !+
|
||||||
|
inc.z addr+1
|
||||||
|
!:
|
||||||
|
lda.z addr
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z addr+1
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
__b1:
|
||||||
|
cpy #8
|
||||||
|
bcc __b2
|
||||||
|
clc
|
||||||
|
lda.z addr
|
||||||
|
adc #<SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr
|
||||||
|
lda.z addr+1
|
||||||
|
adc #>SCREEN2_COLOR_TABLE
|
||||||
|
sta.z set_vram_write_addr.addr+1
|
||||||
|
jsr set_vram_write_addr
|
||||||
|
ldy #0
|
||||||
|
__b4:
|
||||||
|
cpy #8
|
||||||
|
bcc __b5
|
||||||
|
rts
|
||||||
|
__b5:
|
||||||
|
stx VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b4
|
||||||
|
__b2:
|
||||||
|
lda (source),y
|
||||||
|
sta VDP_DATA
|
||||||
|
iny
|
||||||
|
jmp __b1
|
||||||
|
}
|
||||||
|
// sets the VRAM read address on the TMS9918
|
||||||
|
// set_vram_read_addr(word zp($17) addr)
|
||||||
|
set_vram_read_addr: {
|
||||||
|
.label addr = $17
|
||||||
|
lda.z addr
|
||||||
|
sta VDP_REG
|
||||||
|
lda.z addr+1
|
||||||
|
and #$3f
|
||||||
|
sta VDP_REG
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
.segment Data
|
||||||
|
FONT: .byte 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 8, 0, $14, $14, $14, 0, 0, 0, 0, 0, $14, $14, $3e, $14, $3e, $14, $14, 0, 8, $1e, $28, $1c, $a, $3c, 8, 0, $30, $32, 4, 8, $10, $26, 6, 0, $10, $28, $28, $10, $2a, $24, $1a, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, $10, $20, $20, $20, $10, 8, 0, 8, 4, 2, 2, 2, 4, 8, 0, 8, $2a, $1c, 8, $1c, $2a, 8, 0, 0, 8, 8, $3e, 8, 8, 0, 0, 0, 0, 0, 0, 8, 8, $10, 0, 0, 0, 0, $3e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 2, 4, 8, $10, $20, 0, 0, $1c, $22, $26, $2a, $32, $22, $1c, 0, 8, $18, 8, 8, 8, 8, $1c, 0, $1c, $22, 2, $c, $10, $20, $3e, 0, $3e, 2, 4, $c, 2, $22, $1c, 0, 4, $c, $14, $24, $3e, 4, 4, 0, $3e, $20, $3c, 2, 2, $22, $1c, 0, $e, $10, $20, $3c, $22, $22, $1c, 0, $3e, 2, 4, 8, $10, $20, $20, 0, $1c, $22, $22, $1c, $22, $22, $1c, 0, $1c, $22, $22, $1e, 2, 4, $38, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0, 8, 0, 8, 8, $10, 0, 4, 8, $10, $20, $10, 8, 4, 0, 0, 0, $3e, 0, $3e, 0, 0, 0, $10, 8, 4, 2, 4, 8, $10, 0, $1c, $22, 4, 8, 8, 0, 8, 0, $1c, $22, $2a, $2e, $2c, $20, $1c, 0, 8, $14, $22, $22, $3e, $22, $22, 0, $3c, $22, $22, $3c, $22, $22, $3c, 0, $1c, $22, $20, $20, $20, $22, $1c, 0, $38, $24, $22, $22, $22, $24, $38, 0, $3e, $20, $20, $38, $20, $20, $3e, 0, $3e, $20, $20, $38, $20, $20, $20, 0, $1e, $20, $20, $20, $26, $22, $1e, 0, $22, $22, $22, $3e, $22, $22, $22, 0, $1c, 8, 8, 8, 8, 8, $1c, 0, 2, 2, 2, 2, 2, $22, $1c, 0, $22, $24, $28, $30, $28, $24, $22, 0, $20, $20, $20, $20, $20, $20, $3e, 0, $22, $36, $2a, $2a, $22, $22, $22, 0, $22, $22, $32, $2a, $26, $22, $22, 0, $1c, $22, $22, $22, $22, $22, $1c, 0, $3c, $22, $22, $3c, $20, $20, $20, 0, $1c, $22, $22, $22, $2a, $24, $1a, 0, $3c, $22, $22, $3c, $28, $24, $22, 0, $1c, $22, $20, $1c, 2, $22, $1c, 0, $3e, 8, 8, 8, 8, 8, 8, 0, $22, $22, $22, $22, $22, $22, $1c, 0, $22, $22, $22, $22, $22, $14, 8, 0, $22, $22, $22, $2a, $2a, $36, $22, 0, $22, $22, $14, 8, $14, $22, $22, 0, $22, $22, $14, 8, 8, 8, 8, 0, $3e, 2, 4, 8, $10, $20, $3e, 0, $3e, $30, $30, $30, $30, $30, $3e, 0, 0, $20, $10, 8, 4, 2, 0, 0, $3e, 6, 6, 6, 6, 6, $3e, 0, 8, $14, $22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, $3e, $10, 8, 4, 0, 0, 0, 0, 0, 0, 0, $1c, 2, $1e, $22, $1e, 0, $20, $20, $3c, $22, $22, $22, $3c, 0, 0, 0, $1e, $20, $20, $20, $1e, 0, 2, 2, $1e, $22, $22, $22, $1e, 0, 0, 0, $1c, $22, $3e, $20, $1e, 0, $c, $12, $10, $3c, $10, $10, $10, 0, 0, 0, $1c, $22, $22, $1e, 2, $1c, $20, $20, $3c, $22, $22, $22, $22, 0, 8, 0, $18, 8, 8, 8, $1c, 0, 2, 0, 6, 2, 2, 2, $12, $c, $20, $20, $22, $24, $38, $24, $22, 0, $18, 8, 8, 8, 8, 8, $1c, 0, 0, 0, $34, $2a, $2a, $2a, $22, 0, 0, 0, $3c, $22, $22, $22, $22, 0, 0, 0, $1c, $22, $22, $22, $1c, 0, 0, 0, $3c, $22, $22, $3c, $20, $20, 0, 0, $1e, $22, $22, $1e, 2, 2, 0, 0, $2e, $30, $20, $20, $20, 0, 0, 0, $1e, $20, $1c, 2, $3c, 0, $10, $10, $3c, $10, $10, $12, $c, 0, 0, 0, $22, $22, $22, $26, $1a, 0, 0, 0, $22, $22, $22, $14, 8, 0, 0, 0, $22, $22, $2a, $2a, $14, 0, 0, 0, $22, $14, 8, $14, $22, 0, 0, 0, $22, $24, $14, $18, 8, $30, 0, 0, $3e, 4, 8, $10, $3e, 0, 6, 8, 8, $30, 8, 8, 6, 0, 8, 8, 8, 8, 8, 8, 8, 8, $30, 8, 8, 6, 8, 8, $30, 0, $1a, $2c, 0, 0, 0, 0, 0, 0
|
||||||
|
.fill 8, 0
|
||||||
|
SCREEN1_TABLE: .byte 0, $c0, 5, $80, 1, $20, 0, $25
|
||||||
|
SCREEN2_TABLE: .byte 2, $c0, $e, $ff, 3, $76, 3, $25
|
||||||
|
s: .text "*** P-LAB VIDEO CARD SYSTEM ***"
|
||||||
|
.byte 0
|
||||||
|
s1: .text "16K VRAM BYTES FREE"
|
||||||
|
.byte 0
|
||||||
|
s2: .text "READY."
|
||||||
|
.byte 0
|
Loading…
Reference in New Issue
Block a user