string input; reunite screen1 and screen 2 constants

This commit is contained in:
nino-porcino 2021-12-16 18:35:25 +01:00
parent 56f88849f0
commit 397818f947
3 changed files with 190 additions and 84 deletions

View File

@ -1,3 +1,13 @@
// TODO a bitmapped text writing routine (double size ecc)
// TODO console like text output in screen 2
// TODO more fonts (C64 and PET/VIC20)
// TODO how to switch fonts?
// TODO do fonts need to start from 32 or 0?
// TODO sprite routines
// TODO test the interrupt routines
// TODO provide a single .h file (tms_lib.h or tms9918.h?)
// TODO finalize hexdump.js and update README.md
#pragma encoding(ascii) // encode strings in plain ascii
#ifdef APPLE1
@ -47,6 +57,22 @@ const byte COLOR_MAGENTA = 0xD;
const byte COLOR_GREY = 0xE;
const byte COLOR_WHITE = 0xF;
// The library has a fixed VRAM memory layout valid for SCREEN 1 and 2
//
// 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 TMS_NAME_TABLE = 0x3800;
const word TMS_COLOR_TABLE = 0x2000;
const word TMS_PATTERN_TABLE = 0x0000;
const word TMS_SPRITE_ATTRS = 0x3b00;
const word TMS_SPRITE_PATTERNS = 0x1800;
// macro for combining foreground and background into a single byte value
#define FG_BG(f,b) (((f)<<4)|(b))
@ -62,6 +88,14 @@ const byte COLOR_WHITE = 0xF;
#define TMS_READ_CTRL_PORT (*VDP_REG);
#define TMS_READ_DATA_PORT (*VDP_DATA);
// buffer containing the last register values, because TMS registers are write only
byte tms_regs_latch[8];
// cursor coordinates for the console functions
byte tms_cursor_x;
byte tms_cursor_y;
byte tms_reverse;
// sets the VRAM address on the TMS9918 for a write operation
void tms_set_vram_write_addr(word addr) {
TMS_WRITE_CTRL_PORT(LOBYTE(addr));
@ -74,9 +108,6 @@ void tms_set_vram_read_addr(word addr) {
TMS_WRITE_CTRL_PORT((HIBYTE(addr) & HIADDRESS_MASK)|READ_FROM_VRAM);
}
// buffer containing the last register values, because TMS registers are write only
byte tms_regs_latch[8];
// writes a value to a TMS9918 register (0-7)
void tms_write_reg(byte regnum, byte val) {
TMS_WRITE_CTRL_PORT(val);

View File

@ -1,51 +1,134 @@
byte SCREEN1_TABLE[8] = {
0x00, 0xc0, 0x05, 0x80, 0x01, 0x20, 0x00, 0x25
};
byte SCREEN1_TABLE[8] = { 0x00, 0xc0, 0x0e, 0x80, 0x00, 0x76, 0x03, 0x25 };
// 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);
const word SCREEN1_SIZE = (32*24);
// loads the font on the pattern table
void screen1_load_font() {
byte *source = FONT;
// start writing into VRAM from space character (32..127)
tms_set_vram_write_addr(SCREEN1_PATTERN_TABLE+(32*8));
tms_set_vram_write_addr(TMS_PATTERN_TABLE+(32*8));
for(word i=768;i!=0;i--) {
TMS_WRITE_DATA_PORT(*source++);
}
// reverse font (32..127)
source = FONT;
tms_set_vram_write_addr(SCREEN1_PATTERN_TABLE+((128+32)*8));
tms_set_vram_write_addr(TMS_PATTERN_TABLE+((128+32)*8));
for(word i=768;i!=0;i--) {
TMS_WRITE_DATA_PORT(~(*source++));
}
}
// holds the cursor location for the putchar routine
word screen1_cursor;
void screen1_cls() {
// fills name table with spaces (32)
tms_set_vram_write_addr(TMS_NAME_TABLE);
for(word i=SCREEN1_SIZE;i!=0;i--) {
TMS_WRITE_DATA_PORT(32);
}
tms_cursor_x = 0;
tms_cursor_y = 0;
}
void screen1_scroll_up() {
word source = TMS_NAME_TABLE + 1*32;
word dest = TMS_NAME_TABLE + 0*32;
word count = 768-32;
for(;count!=0;source++,dest++,count--) {
tms_set_vram_read_addr(source);
byte c = TMS_READ_DATA_PORT;
tms_set_vram_write_addr(dest);
TMS_WRITE_DATA_PORT(c);
}
// fill last line with spaces
for(word i=0;i<32;i++) {
TMS_WRITE_DATA_PORT(32); NOP; NOP; NOP; NOP;
}
}
void screen1_prepare() {
// fill name table with spaces (32)
screen1_cls();
// fill pattern table with 0
tms_set_vram_write_addr(TMS_PATTERN_TABLE);
for(word i=256*8;i!=0;i--) {
TMS_WRITE_DATA_PORT(0);
}
// fill color table with black on white
tms_set_vram_write_addr(TMS_COLOR_TABLE);
for(byte i=32;i!=0;i--) {
TMS_WRITE_DATA_PORT(FG_BG(COLOR_BLACK,COLOR_WHITE));
}
}
#ifdef VIC20
#define CHR_BACKSPACE 20
#else
#define CHR_BACKSPACE 8
#endif
#define CHR_HOME 11
#define CHR_CLS 12
#define CHR_REVERSE_ON 15
#define CHR_RETURN 13
#define CHR_REVERSE_OFF 14
#define CHR_SPACE 32
#define CHR_REVSPACE (32+128)
#define HOME "\x0b"
#define CLS "\x0c"
#define REVERSE_OFF "\x0e"
#define REVERSE_ON "\x0f"
// prints character to TMS (SCREEN 1 MODE)
void screen1_putc(byte c) {
tms_set_vram_write_addr(screen1_cursor++);
TMS_WRITE_DATA_PORT(c);
if(c==CHR_CLS) {
screen1_cls();
}
else if(c==CHR_HOME) {
tms_cursor_x = 0;
tms_cursor_y = 0;
}
else if(c==CHR_REVERSE_OFF) {
// shift out as reverse off
tms_reverse = 0;
}
else if(c==CHR_REVERSE_ON) {
// shift in as reverse on
tms_reverse = 1;
}
else if(c==CHR_BACKSPACE) {
// backspace
if(tms_cursor_x!=0) {
tms_cursor_x--;
}
else {
if(tms_cursor_y!=0) {
tms_cursor_y--;
tms_cursor_x = 31;
}
}
}
else {
if(c=='\r'||c=='\n') {
tms_cursor_x=31;
}
else {
if(tms_reverse) c |= 128;
word addr = TMS_NAME_TABLE + (word) tms_cursor_y * 32 + tms_cursor_x;
tms_set_vram_write_addr(addr);
TMS_WRITE_DATA_PORT(c);
}
if(tms_cursor_x==31) {
tms_cursor_x=0;
if(tms_cursor_y==23) screen1_scroll_up();
else tms_cursor_y++;
}
else tms_cursor_x++;
}
}
// prints a 0 terminated string to TMS (SCREEN 1 MODE)
@ -56,31 +139,40 @@ void screen1_puts(byte *s) {
}
}
void screen1_home() {
screen1_cursor = SCREEN1_NAME_TABLE;
inline void screen1_locate(byte x, byte y) {
tms_cursor_x = x;
tms_cursor_y = y;
}
void screen1_locate(byte x, byte y) {
screen1_cursor = SCREEN1_NAME_TABLE + ((word)y)*32 + x;
}
void screen1_prepare() {
// fills name table with spaces (32)
tms_set_vram_write_addr(SCREEN1_NAME_TABLE);
for(word i=SCREEN1_SIZE;i!=0;i--) {
TMS_WRITE_DATA_PORT(32);
}
// fill pattern table with 0
tms_set_vram_write_addr(SCREEN1_PATTERN_TABLE);
for(word i=256*8;i!=0;i--) {
TMS_WRITE_DATA_PORT(0);
}
// fill color table with black on white
tms_set_vram_write_addr(SCREEN1_COLOR_TABLE);
for(byte i=32;i!=0;i--) {
TMS_WRITE_DATA_PORT(FG_BG(COLOR_BLACK,COLOR_WHITE));
void screen1_strinput(byte *buffer, byte max_length) {
byte pos=0;
screen1_putc(CHR_REVSPACE);
screen1_putc(CHR_BACKSPACE);
while(1) {
byte key = apple1_getkey();
if(key==CHR_RETURN) {
buffer[pos] = 0;
screen1_putc(CHR_SPACE);
screen1_putc(CHR_BACKSPACE);
return;
}
else if(key==CHR_BACKSPACE) {
if(pos!=0) {
pos--;
screen1_putc(CHR_BACKSPACE);
screen1_putc(CHR_REVSPACE);
screen1_putc(CHR_SPACE);
screen1_putc(CHR_BACKSPACE);
screen1_putc(CHR_BACKSPACE);
}
}
else if(key>=32 && key<=128) {
if(pos < max_length) {
buffer[pos++] = key;
screen1_putc(key);
screen1_putc(CHR_REVSPACE);
screen1_putc(CHR_BACKSPACE);
}
}
}
}

View File

@ -1,34 +1,17 @@
byte SCREEN2_TABLE[8] = {
0x02, 0xc0, 0x0e, 0xff, 0x03, 0x76, 0x03, 0x25
};
byte SCREEN2_TABLE[8] = { 0x02, 0xc0, 0x0e, 0xff, 0x03, 0x76, 0x03, 0x25 };
// 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);
const word SCREEN2_SIZE = (32*24);
// prepare the screen 2 to be used as a bitmap
void screen2_init_bitmap(byte color) {
// erase the first sprite pattern
tms_set_vram_write_addr(SCREEN2_SPRITE_PATTERNS); // start writing in the sprite patterns
tms_set_vram_write_addr(TMS_SPRITE_PATTERNS); // start writing in the sprite patterns
for(byte i=0;i<8;i++) {
TMS_WRITE_DATA_PORT(0); NOP;
}
// set all sprite coordinates to 0
tms_set_vram_write_addr(SCREEN2_SPRITE_ATTRS); // start writing in the sprite attribute
tms_set_vram_write_addr(TMS_SPRITE_ATTRS); // start writing in the sprite attribute
for(byte i=0;i<32;i++) {
TMS_WRITE_DATA_PORT(0); NOP; // y coordinate
TMS_WRITE_DATA_PORT(0); NOP; // x coordinate
@ -37,21 +20,21 @@ void screen2_init_bitmap(byte color) {
}
// fill pattern table with 0 (clear screen)
tms_set_vram_write_addr(SCREEN2_PATTERN_TABLE);
tms_set_vram_write_addr(TMS_PATTERN_TABLE);
for(word i=768*8;i!=0;i--) {
TMS_WRITE_DATA_PORT(0);
NOP;
}
// fill color table with black on white
tms_set_vram_write_addr(SCREEN2_COLOR_TABLE);
tms_set_vram_write_addr(TMS_COLOR_TABLE);
for(word i=768*8;i!=0;i--) {
TMS_WRITE_DATA_PORT(color);
NOP;
}
// fills name table x3 with increasing numbers
tms_set_vram_write_addr(SCREEN2_NAME_TABLE);
tms_set_vram_write_addr(TMS_NAME_TABLE);
for(word i=0;i<SCREEN2_SIZE;i++) {
TMS_WRITE_DATA_PORT(i & 0xFF);
NOP;
@ -61,8 +44,8 @@ void screen2_init_bitmap(byte color) {
void screen2_putc(byte ch, byte x, byte y, byte col) {
byte *source = &FONT[(word)(ch-32)*8];
word addr = x*8 + y*256;
tms_set_vram_write_addr(SCREEN2_PATTERN_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA_PORT(source[i]);
tms_set_vram_write_addr(SCREEN2_COLOR_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA_PORT(col);
tms_set_vram_write_addr(TMS_PATTERN_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA_PORT(source[i]);
tms_set_vram_write_addr(TMS_COLOR_TABLE + addr); for(byte i=0;i<8;i++) TMS_WRITE_DATA_PORT(col);
}
void screen2_puts(byte x, byte y, byte col, char *s) {
@ -76,16 +59,16 @@ void screen2_puts(byte x, byte y, byte col, char *s) {
#define PLOT_MODE_SET 1
#define PLOT_MODE_INVERT 2
byte SCREEN2_PLOT_MODE = PLOT_MODE_SET;
byte screen2_plot_mode = PLOT_MODE_SET;
void screen2_plot(byte x, byte y) {
byte pow2_table_reversed[8] = { 128,64,32,16,8,4,2,1 };
word paddr = SCREEN2_PATTERN_TABLE + (word)(x & 0b11111000) + (word)(y & 0b11111000)*32 + y%8;
word paddr = TMS_PATTERN_TABLE + (word)(x & 0b11111000) + (word)(y & 0b11111000)*32 + y%8;
tms_set_vram_read_addr(paddr);
byte data = TMS_READ_DATA_PORT;
byte mask = pow2_table_reversed[x%8];
tms_set_vram_write_addr(paddr);
switch(SCREEN2_PLOT_MODE) {
switch(screen2_plot_mode) {
case PLOT_MODE_RESET:
data &= ~mask;
break;
@ -105,7 +88,7 @@ signed int vti_abs(signed int x) {
}
// http://members.chello.at/~easyfilter/bresenham.html
void vti_line(byte _x0, byte _y0, byte _x1, byte _y1) {
void screen2_line(byte _x0, byte _y0, byte _x1, byte _y1) {
signed int x0 = (signed int) _x0;
signed int x1 = (signed int) _x1;