Because that mode behaves exactly like in a regular TMS9918, a new driver for TMS9918 has been added in blkfs and SMS' VDP now uses it. Also, fix broken 5x7 font.master
@@ -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?) ) |
@@ -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 ; |
@@ -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 ; |
@@ -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?) ) |
@@ -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 ; |
@@ -1,3 +0,0 @@ | |||||
: CELL! ( tilenum pos ) | |||||
2 * 0x7800 OR _ctl ( tilenum ) | |||||
0x5e MOD _data 1 _zero ; |
@@ -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 ; |
@@ -4,8 +4,8 @@ | |||||
0xddca CONSTANT PS_ADDR | 0xddca CONSTANT PS_ADDR | ||||
RS_ADDR 0x80 - CONSTANT SYSVARS | RS_ADDR 0x80 - CONSTANT SYSVARS | ||||
0xc000 CONSTANT HERESTART | 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 0x70 + CONSTANT GRID_MEM | ||||
SYSVARS 0x72 + CONSTANT CPORT_MEM | SYSVARS 0x72 + CONSTANT CPORT_MEM | ||||
0x3f CONSTANT CPORT_CTL | 0x3f CONSTANT CPORT_CTL | ||||
@@ -27,7 +27,8 @@ CURRENT @ XCURRENT ! | |||||
283 335 LOADR ( boot.z80 ) | 283 335 LOADR ( boot.z80 ) | ||||
353 LOAD ( xcomp core low ) | 353 LOAD ( xcomp core low ) | ||||
CREATE ~FNT CPFNT7x7 | CREATE ~FNT CPFNT7x7 | ||||
603 608 LOADR ( VDP ) | |||||
470 472 LOADR ( TMS9918 ) | |||||
602 604 LOADR ( VDP ) | |||||
402 404 LOADR ( Grid ) | 402 404 LOADR ( Grid ) | ||||
625 626 LOADR ( SMS ports ) | 625 626 LOADR ( SMS ports ) | ||||
612 617 LOADR ( PAD ) | 612 617 LOADR ( PAD ) | ||||
@@ -5,8 +5,8 @@ | |||||
0xddca CONSTANT PS_ADDR | 0xddca CONSTANT PS_ADDR | ||||
RS_ADDR 0x80 - CONSTANT SYSVARS | RS_ADDR 0x80 - CONSTANT SYSVARS | ||||
0xc000 CONSTANT HERESTART | 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 0x70 + CONSTANT GRID_MEM | ||||
SYSVARS 0x72 + CONSTANT CPORT_MEM | SYSVARS 0x72 + CONSTANT CPORT_MEM | ||||
0x3f CONSTANT CPORT_CTL | 0x3f CONSTANT CPORT_CTL | ||||
@@ -28,7 +28,8 @@ CURRENT @ XCURRENT ! | |||||
283 335 LOADR ( boot.z80 ) | 283 335 LOADR ( boot.z80 ) | ||||
353 LOAD ( xcomp core low ) | 353 LOAD ( xcomp core low ) | ||||
CREATE ~FNT CPFNT7x7 | CREATE ~FNT CPFNT7x7 | ||||
603 608 LOADR ( VDP ) | |||||
470 472 LOADR ( TMS9918 ) | |||||
602 604 LOADR ( VDP ) | |||||
402 404 LOADR ( Grid ) | 402 404 LOADR ( Grid ) | ||||
625 626 LOADR ( SMS ports ) | 625 626 LOADR ( SMS ports ) | ||||
620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR | 620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR | ||||
@@ -6,8 +6,8 @@ | |||||
0xddca CONSTANT PS_ADDR | 0xddca CONSTANT PS_ADDR | ||||
RS_ADDR 0x80 - CONSTANT SYSVARS | RS_ADDR 0x80 - CONSTANT SYSVARS | ||||
0xc000 CONSTANT HERESTART | 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 0x70 + CONSTANT GRID_MEM | ||||
SYSVARS 0x72 + CONSTANT CPORT_MEM | SYSVARS 0x72 + CONSTANT CPORT_MEM | ||||
0x3f CONSTANT CPORT_CTL | 0x3f CONSTANT CPORT_CTL | ||||
@@ -29,7 +29,8 @@ CURRENT @ XCURRENT ! | |||||
283 335 LOADR ( boot.z80 ) | 283 335 LOADR ( boot.z80 ) | ||||
353 LOAD ( xcomp core low ) | 353 LOAD ( xcomp core low ) | ||||
CREATE ~FNT CPFNT7x7 | CREATE ~FNT CPFNT7x7 | ||||
603 608 LOADR ( VDP ) | |||||
470 472 LOADR ( TMS9918 ) | |||||
602 604 LOADR ( VDP ) | |||||
402 404 LOADR ( Grid ) | 402 404 LOADR ( Grid ) | ||||
625 626 LOADR ( SMS ports ) | 625 626 LOADR ( SMS ports ) | ||||
620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR | 620 LOAD ( PAD ) : (ps2kc) (ps2kcA) ; 411 414 LOADR | ||||
@@ -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! |
@@ -9,4 +9,5 @@ MASTER INDEX | |||||
400 AT28 EEPROM driver 401 Grid subsystem | 400 AT28 EEPROM driver 401 Grid subsystem | ||||
410 PS/2 keyboard subsystem 418 Z80 SPI Relay driver | 410 PS/2 keyboard subsystem 418 Z80 SPI Relay driver | ||||
420 SD Card subsystem 440 8086 boot code | 420 SD Card subsystem 440 8086 boot code | ||||
470-519 unused 520 Fonts | |||||
470 Z80 TMS9918 driver | |||||
480-519 unused 520 Fonts |
@@ -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 |
@@ -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 |
@@ -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 ) ; |
@@ -9,7 +9,7 @@ | |||||
DUP I 5 * + _g | DUP I 5 * + _g | ||||
LOOP ; | LOOP ; | ||||
: CPFNT5x7 | : 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! ) | 535 BLK@ BLK( 12 _l 448 + 10 _l DROP ( 94! ) | ||||
; | ; |
@@ -34,7 +34,7 @@ static xcb_gcontext_t fg; | |||||
static xcb_drawable_t win; | static xcb_drawable_t win; | ||||
// pixels to draw. We draw them in one shot. | // 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 Machine *m; | ||||
static VDP vdp; | static VDP vdp; | ||||
@@ -144,19 +144,19 @@ void draw_pixels() | |||||
xcb_clear_area( | xcb_clear_area( | ||||
conn, 0, win, 0, 0, geom->width, geom->height); | conn, 0, win, 0, 0, geom->width, geom->height); | ||||
// Figure out inner size to maximize our screen's aspect ratio | // 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 | // 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 innerx = (geom->width - innerw) / 2; | ||||
int innery = (geom->height - innerh) / 2; | int innery = (geom->height - innerh) / 2; | ||||
free(geom); | free(geom); | ||||
int drawcnt = 0; | int drawcnt = 0; | ||||
for (int i=0; i<VDP_SCREENW; i++) { | |||||
for (int j=0; j<VDP_SCREENH; j++) { | |||||
for (int i=0; i<vdp.tms.width; i++) { | |||||
for (int j=0; j<vdp.tms.height; j++) { | |||||
if (vdp_pixel(&vdp, i, j)) { | if (vdp_pixel(&vdp, i, j)) { | ||||
int x = innerx + (i*psize); | int x = innerx + (i*psize); | ||||
int y = innery + (j*psize); | int y = innery + (j*psize); | ||||
@@ -1,6 +1,11 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "sms_vdp.h" | #include "sms_vdp.h" | ||||
static bool _is_mode4(VDP *vdp) | |||||
{ | |||||
return (vdp->tms.regs[0]&0x4); | |||||
} | |||||
void vdp_init(VDP *vdp) | void vdp_init(VDP *vdp) | ||||
{ | { | ||||
tms_init(&vdp->tms); | 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); | vdp->tms.curaddr = TMS_VRAM_SIZE + (vdp->tms.cmdlsb&0x1f); | ||||
} else { | } else { | ||||
tms_cmd_wr(&vdp->tms, val); | 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) | 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; | return 0; | ||||
} | } | ||||
if (y >= VDP_SCREENH) { | |||||
if (y >= tms->height) { | |||||
return 0; | return 0; | ||||
} | } | ||||
TMS9918 *tms = &vdp->tms; | |||||
// name table offset | // name table offset | ||||
uint16_t offset = (tms->regs[2] & 0xe) << 10; | uint16_t offset = (tms->regs[2] & 0xe) << 10; | ||||
offset += ((y/8) << 6) + ((x/8) << 1); | offset += ((y/8) << 6) + ((x/8) << 1); | ||||
@@ -1,8 +1,6 @@ | |||||
#include "tms9918.h" | #include "tms9918.h" | ||||
#define VDP_CRAM_SIZE 0x20 | #define VDP_CRAM_SIZE 0x20 | ||||
#define VDP_SCREENW (32*8) | |||||
#define VDP_SCREENH (24*8) | |||||
typedef struct { | typedef struct { | ||||
TMS9918 tms; | TMS9918 tms; | ||||
@@ -1,12 +1,34 @@ | |||||
#include <stdio.h> | |||||
#include <string.h> | #include <string.h> | ||||
#include "tms9918.h" | #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) | void tms_init(TMS9918 *tms) | ||||
{ | { | ||||
memset(tms->vram, 0, TMS_VRAM_SIZE); | memset(tms->vram, 0, TMS_VRAM_SIZE); | ||||
memset(tms->regs, 0, 0x10); | memset(tms->regs, 0, 0x10); | ||||
tms->has_cmdlsb = false; | tms->has_cmdlsb = false; | ||||
tms->curaddr = 0; | tms->curaddr = 0; | ||||
tms->width = 40*6; | |||||
tms->height = 24*8; | |||||
} | } | ||||
uint8_t tms_cmd_rd(TMS9918 *tms) | 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) | // Returns a 8-bit RGB value (0b00bbggrr) | ||||
uint8_t tms_pixel(TMS9918 *tms, uint16_t x, uint16_t y) | 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; | |||||
} | |||||
} | } |
@@ -13,6 +13,8 @@ typedef struct { | |||||
uint8_t cmdlsb; | uint8_t cmdlsb; | ||||
bool has_cmdlsb; | bool has_cmdlsb; | ||||
uint16_t curaddr; | uint16_t curaddr; | ||||
uint16_t width; // in pixels | |||||
uint16_t height; // in pixels | |||||
} TMS9918; | } TMS9918; | ||||
void tms_init(TMS9918 *tms); | void tms_init(TMS9918 *tms); | ||||