diff --git a/arch/z80/sms/blk/602 b/arch/z80/sms/blk/602 index dfd90b6..28d617c 100644 --- a/arch/z80/sms/blk/602 +++ b/arch/z80/sms/blk/602 @@ -1,16 +1,11 @@ -VDP Driver - -Implement (emit) on the console. Characters start at the top -left. Every (emit) call converts the ASCII char received to its -internal font, then put that char on screen, advancing the -cursor by one. When reaching the end of the line (33rd char), -wrap to the next. - -In the future, there's going to be a scrolling mechanism when -we reach the bottom of the screen, but for now, when the end of -the screen is reached, we wrap up to the top. - -When reaching a new line, we clear that line and the next to -help readability. - -Load range: 623-628 +( VDP Driver. requires TMS9918 driver. Load range B602-B604. ) +CREATE _idat +0b00000100 C, 0x80 C, ( Bit 2: Select mode 4 ) +0b00000000 C, 0x81 C, +0b00001111 C, 0x82 C, ( Name table: 0x3800, *B0 must be 1* ) +0b11111111 C, 0x85 C, ( Sprite table: 0x3f00 ) +0b11111111 C, 0x86 C, ( sprite use tiles from 0x2000 ) +0b11111111 C, 0x87 C, ( Border uses palette 0xf ) +0b00000000 C, 0x88 C, ( BG X scroll ) +0b00000000 C, 0x89 C, ( BG Y scroll ) +0b11111111 C, 0x8a C, ( Line counter (why have this?) ) diff --git a/arch/z80/sms/blk/603 b/arch/z80/sms/blk/603 index 981342c..ef7ef09 100644 --- a/arch/z80/sms/blk/603 +++ b/arch/z80/sms/blk/603 @@ -1,9 +1,14 @@ -CODE _ctl ( a -- sends LSB then MSB ) - HL POP, chkPS, - A L LDrr, VDP_CTLPORT OUTiA, - A H LDrr, VDP_CTLPORT OUTiA, -;CODE -CODE _data - HL POP, chkPS, - A L LDrr, VDP_DATAPORT OUTiA, -;CODE +: _zero ( x -- send 0 _data x times ) + ( x ) 0 DO 0 _data LOOP ; +( Each row in ~FNT is a row of the glyph and there is 7 of +them. We insert a blank one at the end of those 7. For each +row we set, we need to send 3 zero-bytes because each pixel in +the tile is actually 4 bits because it can select among 16 +palettes. We use only 2 of them, which is why those bytes +always stay zero. ) +: _sfont ( a -- Send font to VDP ) + 7 0 DO C@+ _data 3 _zero LOOP DROP + ( blank row ) 4 _zero ; +: CELL! ( tilenum pos ) + 2 * 0x7800 OR _ctl ( tilenum ) + 0x5e MOD _data 1 _zero ; diff --git a/arch/z80/sms/blk/604 b/arch/z80/sms/blk/604 index 8652804..f3913e1 100644 --- a/arch/z80/sms/blk/604 +++ b/arch/z80/sms/blk/604 @@ -1,9 +1,11 @@ -CODE _blank ( this is way too slow in Forth ) - A XORr, VDP_CTLPORT OUTiA, - A 0x40 LDri, VDP_CTLPORT OUTiA, - HL 0x4000 LDdi, - BEGIN, - A XORr, VDP_DATAPORT OUTiA, - HL DECd, HLZ, - JRNZ, AGAIN, -;CODE +: VDP$ + 9 0 DO _idat I 2 * + @ _ctl LOOP _blank + ( palettes ) + 0xc000 _ctl + ( BG ) 1 _zero 0x3f _data 14 _zero + ( sprite, inverted colors ) 0x3f _data 15 _zero + 0x4000 _ctl 0x5e 0 DO ~FNT I 7 * + _sfont LOOP + ( bit 6, enable display, bit 7, ?? ) 0x81c0 _ctl ; + +: COLS 32 ; +: LINES 24 ; diff --git a/arch/z80/sms/blk/605 b/arch/z80/sms/blk/605 deleted file mode 100644 index 3614357..0000000 --- a/arch/z80/sms/blk/605 +++ /dev/null @@ -1,10 +0,0 @@ -CREATE _idat -0b00000100 C, 0x80 C, ( Bit 2: Select mode 4 ) -0b00000000 C, 0x81 C, -0b00001111 C, 0x82 C, ( Name table: 0x3800, *B0 must be 1* ) -0b11111111 C, 0x85 C, ( Sprite table: 0x3f00 ) -0b11111111 C, 0x86 C, ( sprite use tiles from 0x2000 ) -0b11111111 C, 0x87 C, ( Border uses palette 0xf ) -0b00000000 C, 0x88 C, ( BG X scroll ) -0b00000000 C, 0x89 C, ( BG Y scroll ) -0b11111111 C, 0x8a C, ( Line counter (why have this?) ) diff --git a/arch/z80/sms/blk/606 b/arch/z80/sms/blk/606 deleted file mode 100644 index e81e993..0000000 --- a/arch/z80/sms/blk/606 +++ /dev/null @@ -1,12 +0,0 @@ -: _zero ( x -- send 0 _data x times ) - ( x ) 0 DO 0 _data LOOP ; - -( Each row in ~FNT is a row of the glyph and there is 7 of -them. We insert a blank one at the end of those 7. For each -row we set, we need to send 3 zero-bytes because each pixel in -the tile is actually 4 bits because it can select among 16 -palettes. We use only 2 of them, which is why those bytes -always stay zero. ) -: _sfont ( a -- Send font to VDP ) - 7 0 DO C@+ _data 3 _zero LOOP DROP - ( blank row ) 4 _zero ; diff --git a/arch/z80/sms/blk/607 b/arch/z80/sms/blk/607 deleted file mode 100644 index 81d03b6..0000000 --- a/arch/z80/sms/blk/607 +++ /dev/null @@ -1,3 +0,0 @@ -: CELL! ( tilenum pos ) - 2 * 0x7800 OR _ctl ( tilenum ) - 0x5e MOD _data 1 _zero ; diff --git a/arch/z80/sms/blk/608 b/arch/z80/sms/blk/608 deleted file mode 100644 index f3913e1..0000000 --- a/arch/z80/sms/blk/608 +++ /dev/null @@ -1,11 +0,0 @@ -: VDP$ - 9 0 DO _idat I 2 * + @ _ctl LOOP _blank - ( palettes ) - 0xc000 _ctl - ( BG ) 1 _zero 0x3f _data 14 _zero - ( sprite, inverted colors ) 0x3f _data 15 _zero - 0x4000 _ctl 0x5e 0 DO ~FNT I 7 * + _sfont LOOP - ( bit 6, enable display, bit 7, ?? ) 0x81c0 _ctl ; - -: COLS 32 ; -: LINES 24 ; diff --git a/arch/z80/sms/xcomp.fs b/arch/z80/sms/xcomp.fs index 1768b6c..cbd046b 100644 --- a/arch/z80/sms/xcomp.fs +++ b/arch/z80/sms/xcomp.fs @@ -4,8 +4,8 @@ 0xddca CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0xc000 CONSTANT HERESTART -0xbf CONSTANT VDP_CTLPORT -0xbe CONSTANT VDP_DATAPORT +0xbf CONSTANT TMS_CTLPORT +0xbe CONSTANT TMS_DATAPORT SYSVARS 0x70 + CONSTANT GRID_MEM SYSVARS 0x72 + CONSTANT CPORT_MEM 0x3f CONSTANT CPORT_CTL @@ -27,7 +27,8 @@ CURRENT @ XCURRENT ! 283 335 LOADR ( boot.z80 ) 353 LOAD ( xcomp core low ) CREATE ~FNT CPFNT7x7 -603 608 LOADR ( VDP ) +470 472 LOADR ( TMS9918 ) +602 604 LOADR ( VDP ) 402 404 LOADR ( Grid ) 625 626 LOADR ( SMS ports ) 612 617 LOADR ( PAD ) diff --git a/arch/z80/sms/xcompkbd.fs b/arch/z80/sms/xcompkbd.fs index 467d36b..909cb49 100644 --- a/arch/z80/sms/xcompkbd.fs +++ b/arch/z80/sms/xcompkbd.fs @@ -5,8 +5,8 @@ 0xddca CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0xc000 CONSTANT HERESTART -0xbf CONSTANT VDP_CTLPORT -0xbe CONSTANT VDP_DATAPORT +0xbf CONSTANT TMS_CTLPORT +0xbe CONSTANT TMS_DATAPORT SYSVARS 0x70 + CONSTANT GRID_MEM SYSVARS 0x72 + CONSTANT CPORT_MEM 0x3f CONSTANT CPORT_CTL @@ -28,7 +28,8 @@ CURRENT @ XCURRENT ! 283 335 LOADR ( boot.z80 ) 353 LOAD ( xcomp core low ) CREATE ~FNT CPFNT7x7 -603 608 LOADR ( VDP ) +470 472 LOADR ( TMS9918 ) +602 604 LOADR ( VDP ) 402 404 LOADR ( Grid ) 625 626 LOADR ( SMS ports ) 620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR diff --git a/arch/z80/sms/xcompsdc.fs b/arch/z80/sms/xcompsdc.fs index f4b3337..6daac4b 100644 --- a/arch/z80/sms/xcompsdc.fs +++ b/arch/z80/sms/xcompsdc.fs @@ -6,8 +6,8 @@ 0xddca CONSTANT PS_ADDR RS_ADDR 0x80 - CONSTANT SYSVARS 0xc000 CONSTANT HERESTART -0xbf CONSTANT VDP_CTLPORT -0xbe CONSTANT VDP_DATAPORT +0xbf CONSTANT TMS_CTLPORT +0xbe CONSTANT TMS_DATAPORT SYSVARS 0x70 + CONSTANT GRID_MEM SYSVARS 0x72 + CONSTANT CPORT_MEM 0x3f CONSTANT CPORT_CTL @@ -29,7 +29,8 @@ CURRENT @ XCURRENT ! 283 335 LOADR ( boot.z80 ) 353 LOAD ( xcomp core low ) CREATE ~FNT CPFNT7x7 -603 608 LOADR ( VDP ) +470 472 LOADR ( TMS9918 ) +602 604 LOADR ( VDP ) 402 404 LOADR ( Grid ) 625 626 LOADR ( SMS ports ) 620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR diff --git a/arch/z80/sms/xcomptextmode.fs b/arch/z80/sms/xcomptextmode.fs new file mode 100644 index 0000000..9ed050e --- /dev/null +++ b/arch/z80/sms/xcomptextmode.fs @@ -0,0 +1,42 @@ +( xcomp using the Text Mode if the VDP. Only works on actual + SMS. The Megadrive's VDP doesn't have TMS9918 modes in it. ) +( 8K of onboard RAM ) +0xdd00 CONSTANT RS_ADDR +( Memory register at the end of RAM. Must not overwrite ) +0xddca CONSTANT PS_ADDR +RS_ADDR 0x80 - CONSTANT SYSVARS +0xc000 CONSTANT HERESTART +0xbf CONSTANT TMS_CTLPORT +0xbe CONSTANT TMS_DATAPORT +SYSVARS 0x70 + CONSTANT GRID_MEM +SYSVARS 0x72 + CONSTANT CPORT_MEM +0x3f CONSTANT CPORT_CTL +0xdc CONSTANT CPORT_D1 +0xdd CONSTANT CPORT_D2 +SYSVARS 0x73 + CONSTANT PS2_MEM +5 LOAD ( z80 assembler ) +: ZFILL, ( u ) 0 DO 0 A, LOOP ; +262 LOAD ( xcomp ) +523 LOAD ( font compiler ) +282 LOAD ( boot.z80.decl ) +270 LOAD ( xcomp overrides ) + +DI, 0x100 JP, 0x62 ZFILL, ( 0x66 ) +RETN, 0x98 ZFILL, ( 0x100 ) +( All set, carry on! ) +CURRENT @ XCURRENT ! +0x100 BIN( ! +283 335 LOADR ( boot.z80 ) +353 LOAD ( xcomp core low ) +CREATE ~FNT CPFNT5x7 +470 472 LOADR ( VDP ) +402 404 LOADR ( Grid ) +625 626 LOADR ( SMS ports ) +620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR +390 LOAD ( xcomp core high ) +(entry) _ +( Update LATEST ) +PC ORG @ 8 + ! +," TMS$ 0 0 AT-XY PS2$ (im1) " EOT, +ORG @ 0x100 - 256 /MOD 2 PC! 2 PC! +H@ 256 /MOD 2 PC! 2 PC! diff --git a/blk/001 b/blk/001 index cd018a1..e90bb4d 100644 --- a/blk/001 +++ b/blk/001 @@ -9,4 +9,5 @@ MASTER INDEX 400 AT28 EEPROM driver 401 Grid subsystem 410 PS/2 keyboard subsystem 418 Z80 SPI Relay driver 420 SD Card subsystem 440 8086 boot code -470-519 unused 520 Fonts +470 Z80 TMS9918 driver +480-519 unused 520 Fonts diff --git a/blk/470 b/blk/470 new file mode 100644 index 0000000..b8fdc3d --- /dev/null +++ b/blk/470 @@ -0,0 +1,12 @@ +( Z80 driver for TMS9918. Implements grid protocol. Requires +TMS_CTLPORT, TMS_DATAPORT and ~FNT from the Font compiler at +B520. Load range B470-472 ) +CODE _ctl ( a -- sends LSB then MSB ) + HL POP, chkPS, + A L LDrr, TMS_CTLPORT OUTiA, + A H LDrr, TMS_CTLPORT OUTiA, +;CODE +CODE _data + HL POP, chkPS, + A L LDrr, TMS_DATAPORT OUTiA, +;CODE diff --git a/blk/471 b/blk/471 new file mode 100644 index 0000000..d6b063f --- /dev/null +++ b/blk/471 @@ -0,0 +1,9 @@ +CODE _blank ( this is way too slow in Forth ) + A XORr, TMS_CTLPORT OUTiA, + A 0x40 LDri, TMS_CTLPORT OUTiA, + HL 0x4000 LDdi, + BEGIN, + A XORr, TMS_DATAPORT OUTiA, + HL DECd, HLZ, + JRNZ, AGAIN, +;CODE diff --git a/blk/472 b/blk/472 new file mode 100644 index 0000000..98cdf96 --- /dev/null +++ b/blk/472 @@ -0,0 +1,16 @@ +( Each row in ~FNT is a row of the glyph and there is 7 of +them. We insert a blank one at the end of those 7. ) +: _sfont ( a -- Send font to TMS ) + 7 0 DO C@+ _data LOOP DROP + ( blank row ) 0 _data ; +: CELL! ( tilenum pos ) + 0x7800 OR _ctl ( tilenum ) + 0x5e MOD _data ; +: COLS 40 ; : LINES 24 ; +: TMS$ + 0x8100 _ctl ( blank screen ) _blank + 0x4000 _ctl 0x5e 0 DO ~FNT I 7 * + _sfont LOOP + 0x820e _ctl ( name table 0x3800 ) + 0x8400 _ctl ( patter table 0x0000 ) + 0x87f0 _ctl ( colors 0 and 1 ) + 0x8000 _ctl 0x81d0 _ctl ( text mode, display on ) ; diff --git a/blk/523 b/blk/523 index c4338da..eda6cb8 100644 --- a/blk/523 +++ b/blk/523 @@ -9,7 +9,7 @@ DUP I 5 * + _g LOOP ; : CPFNT5x7 - 0 , 0 , 0 C, ( space char ) - 534 532 DO I BLK@ BLK( 12 _l 448 + 12 _l DROP LOOP ( 72 ) + 0 , 0 , 0 , 0 C, ( space char ) + 535 532 DO I BLK@ BLK( 12 _l 448 + 12 _l DROP LOOP ( 72 ) 535 BLK@ BLK( 12 _l 448 + 10 _l DROP ( 94! ) ; diff --git a/emul/z80/sms.c b/emul/z80/sms.c index c2ce65a..e90117b 100644 --- a/emul/z80/sms.c +++ b/emul/z80/sms.c @@ -34,7 +34,7 @@ static xcb_gcontext_t fg; static xcb_drawable_t win; // pixels to draw. We draw them in one shot. -static xcb_rectangle_t rectangles[VDP_SCREENW*VDP_SCREENH]; +static xcb_rectangle_t rectangles[(32*8)*(24*8)]; static Machine *m; static VDP vdp; @@ -144,19 +144,19 @@ void draw_pixels() xcb_clear_area( conn, 0, win, 0, 0, geom->width, geom->height); // Figure out inner size to maximize our screen's aspect ratio - int psize = geom->height / VDP_SCREENH; - if (geom->width / VDP_SCREENW < psize) { + int psize = geom->height / vdp.tms.height; + if (geom->width / vdp.tms.width < psize) { // width is the constraint - psize = geom->width / VDP_SCREENW; + psize = geom->width / vdp.tms.width; } - int innerw = psize * VDP_SCREENW; - int innerh = psize * VDP_SCREENH; + int innerw = psize * vdp.tms.width; + int innerh = psize * vdp.tms.height; int innerx = (geom->width - innerw) / 2; int innery = (geom->height - innerh) / 2; free(geom); int drawcnt = 0; - for (int i=0; i #include "sms_vdp.h" +static bool _is_mode4(VDP *vdp) +{ + return (vdp->tms.regs[0]&0x4); +} + void vdp_init(VDP *vdp) { tms_init(&vdp->tms); @@ -18,6 +23,7 @@ void vdp_cmd_wr(VDP *vdp, uint8_t val) vdp->tms.curaddr = TMS_VRAM_SIZE + (vdp->tms.cmdlsb&0x1f); } else { tms_cmd_wr(&vdp->tms, val); + vdp->tms.width = _is_mode4(vdp) ? 32*8 : 40*6; } } } @@ -46,13 +52,16 @@ void vdp_data_wr(VDP *vdp, uint8_t val) uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y) { - if (x >= VDP_SCREENW) { + TMS9918 *tms = &vdp->tms; + if (!_is_mode4(vdp)) { + return tms_pixel(tms, x, y); + } + if (x >= tms->width) { return 0; } - if (y >= VDP_SCREENH) { + if (y >= tms->height) { return 0; } - TMS9918 *tms = &vdp->tms; // name table offset uint16_t offset = (tms->regs[2] & 0xe) << 10; offset += ((y/8) << 6) + ((x/8) << 1); diff --git a/emul/z80/sms_vdp.h b/emul/z80/sms_vdp.h index 86d5b69..f3a98bc 100644 --- a/emul/z80/sms_vdp.h +++ b/emul/z80/sms_vdp.h @@ -1,8 +1,6 @@ #include "tms9918.h" #define VDP_CRAM_SIZE 0x20 -#define VDP_SCREENW (32*8) -#define VDP_SCREENH (24*8) typedef struct { TMS9918 tms; diff --git a/emul/z80/tms9918.c b/emul/z80/tms9918.c index 4cbdd1b..a2a9d57 100644 --- a/emul/z80/tms9918.c +++ b/emul/z80/tms9918.c @@ -1,12 +1,34 @@ +#include #include #include "tms9918.h" +static uint8_t COLORS[0x10] = { // TODO: put actual color codes + 0, // transparent + 0, // black + 1, // medium green + 1, // light green + 1, // dark blue + 1, // light blue + 1, // dark red + 1, // cyan + 1, // medium red + 1, // light red + 1, // dark yellow + 1, // light yellow + 1, // dark green + 1, // magenta + 1, // gray + 1, // white +}; + void tms_init(TMS9918 *tms) { memset(tms->vram, 0, TMS_VRAM_SIZE); memset(tms->regs, 0, 0x10); tms->has_cmdlsb = false; tms->curaddr = 0; + tms->width = 40*6; + tms->height = 24*8; } uint8_t tms_cmd_rd(TMS9918 *tms) @@ -50,5 +72,19 @@ void tms_data_wr(TMS9918 *tms, uint8_t val) // Returns a 8-bit RGB value (0b00bbggrr) uint8_t tms_pixel(TMS9918 *tms, uint16_t x, uint16_t y) { - return 0; // no TMS9918 mode implemented yet + if ((tms->regs[1]&0x18) == 0x10 && (tms->regs[0]&0x40) == 0) { + // Text mode + uint16_t nameoff = (tms->regs[2] & 0xf) << 10; + uint16_t patternoff = (tms->regs[4] & 0x7) << 11; + uint8_t nameid = tms->vram[nameoff+(((y/8) * 40) + (x/6))]; + uint8_t patternline = tms->vram[patternoff+(nameid*8)+(y%8)]; + uint8_t color = tms->regs[7]; + if ((patternline>>(8-(x%6)))&1) { + color >>= 4; + } + color &= 0xf; + return color; + } else { // unsupported mode + return 0; + } } diff --git a/emul/z80/tms9918.h b/emul/z80/tms9918.h index 4c57ebc..db4b8d2 100644 --- a/emul/z80/tms9918.h +++ b/emul/z80/tms9918.h @@ -13,6 +13,8 @@ typedef struct { uint8_t cmdlsb; bool has_cmdlsb; uint16_t curaddr; + uint16_t width; // in pixels + uint16_t height; // in pixels } TMS9918; void tms_init(TMS9918 *tms);