From 22917adcff6c24fcf7ecf4fd435fe59240d4a4e9 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 26 Feb 2022 09:41:38 +0000 Subject: [PATCH] sms, add missing TMS VDP modes --- pico/mode4.c | 174 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 150 insertions(+), 24 deletions(-) diff --git a/pico/mode4.c b/pico/mode4.c index 55127e36..49541c8f 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -3,15 +3,12 @@ * (C) notaz, 2009-2010 * (C) kub, 2021 * - * currently supports VDP mode 4 (SMS and GG) and mode 2+0 (TMS) + * currently supports VDP mode 4 (SMS and GG) and mode 3-0 (TMS) + * modes numbered after the bit numbers used in Sega and TI documentation * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. */ -/* - * TODO: - * - other TMS9918 modes? - */ #include "pico_int.h" #include @@ -55,8 +52,8 @@ static int CollisionDetect(u8 *mb, u16 sx, unsigned int pack, int zoomed) return col; } -/* Mode 4 */ -/*========*/ +/* Mode 4 - SMS Graphics */ +/*=======================*/ static void TileBGM4(u16 sx, int pal) { @@ -333,14 +330,44 @@ static void DrawDisplayM4(int scanline) /* TMS Modes */ /*===========*/ -/* Background, Graphics modes */ +/* Background */ #define TMS_PIXELBG(x,p) \ t = (pack>>(7-p)) & 0x01; \ t = (pal >> (t << 2)) & 0x0f; \ - pd[x] = t; + if (t) \ + pd[x] = t; + +static void TileNormBgM1(u16 sx, unsigned int pack, int pal) /* Text */ +{ + u8 *pd = Pico.est.HighCol + sx; + unsigned int t; + + TMS_PIXELBG(0, 0) + TMS_PIXELBG(1, 1) + TMS_PIXELBG(2, 2) + TMS_PIXELBG(3, 3) + TMS_PIXELBG(4, 4) + TMS_PIXELBG(5, 5) +} + +static void TileNormBgM2(u16 sx, int pal) /* Multicolor */ +{ + u8 *pd = Pico.est.HighCol + sx; + unsigned int pack = 0xf0; + unsigned int t; + + TMS_PIXELBG(0, 0) + TMS_PIXELBG(1, 1) + TMS_PIXELBG(2, 2) + TMS_PIXELBG(3, 3) + TMS_PIXELBG(4, 4) + TMS_PIXELBG(5, 5) + TMS_PIXELBG(6, 6) + TMS_PIXELBG(7, 7) +} -static void TileNormBgGr(u16 sx, unsigned int pack, int pal) +static void TileNormBgMg(u16 sx, unsigned int pack, int pal) /* Graphics */ { u8 *pd = Pico.est.HighCol + sx; unsigned int t; @@ -494,11 +521,105 @@ static void DrawSpritesTMS(void) } } -/* Mode 2 */ -/*========*/ + +/* Mode 1 - Text */ +/*===============*/ + +/* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */ +static void DrawStripM1(const u8 *nametab, const u8 *pattab, int cells_dx, int tilex_ty) +{ + // Draw tiles across screen: + for (; cells_dx > 0; cells_dx += 6, tilex_ty++, cells_dx -= 0x10000) + { + unsigned int pack, pal; + unsigned code; + + code = nametab[tilex_ty & 0x3f]; + pal = Pico.video.reg[7]; + pack = pattab[code << 3]; + TileNormBgM1(cells_dx, pack, pal); + } +} + +/* Draw a scanline */ +static void DrawDisplayM1(int scanline) +{ + struct PicoVideo *pv = &Pico.video; + u8 *nametab, *pattab; + int tilex, dx, cells; + int cellskip = 0; // XXX + int maxcells = 40; + + // name, color, pattern table: + nametab = PicoMem.vramb + ((pv->reg[2]<<10) & 0x3c00); + pattab = PicoMem.vramb + ((pv->reg[4]<<11) & 0x3800); + + nametab += ((scanline>>3) * maxcells); + pattab += (scanline & 0x7); + + tilex = cellskip & 0x1f; + cells = maxcells - cellskip; + dx = (cellskip << 3) + line_offset + 8; + + // tiles + if (!(pv->debug_p & PVD_KILL_B)) + DrawStripM1(nametab, pattab, dx | (cells << 16), tilex | (scanline << 16)); +} + + +/* Mode 2 - Multicolor */ +/*=====================*/ + +/* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */ +static void DrawStripM2(const u8 *nametab, const u8 *pattab, int cells_dx, int tilex_ty) +{ + // Draw tiles across screen: + for (; cells_dx > 0; cells_dx += 8, tilex_ty++, cells_dx -= 0x10000) + { + unsigned int pal; + unsigned code; + + code = nametab[tilex_ty & 0x1f]; + pal = pattab[code << 3]; + TileNormBgM2(cells_dx, pal); + } +} + +/* Draw a scanline */ +static void DrawDisplayM2(int scanline) +{ + struct PicoVideo *pv = &Pico.video; + u8 *nametab, *pattab; + int tilex, dx, cells; + int cellskip = 0; // XXX + int maxcells = 32; + + // name, color, pattern table: + nametab = PicoMem.vramb + ((pv->reg[2]<<10) & 0x3c00); + pattab = PicoMem.vramb + ((pv->reg[4]<<11) & 0x3800); + + nametab += (scanline>>5) << 5; + pattab += (scanline>>2) & 0x7; + + tilex = cellskip & 0x1f; + cells = maxcells - cellskip; + dx = (cellskip << 3) + line_offset + 8; + + // tiles + if (!(pv->debug_p & PVD_KILL_B)) + DrawStripM2(nametab, pattab, dx | (cells << 16), tilex | (scanline << 16)); + + // sprites + if (!(pv->debug_p & PVD_KILL_S_LO)) + DrawSpritesTMS(); +} + + +/* Mode 3 - Graphics II */ +/*======================*/ /* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */ -static void DrawStripM2(const u8 *nametab, const u8 *coltab, const u8 *pattab, int cells_dx, int tilex_ty) +static void DrawStripM3(const u8 *nametab, const u8 *coltab, const u8 *pattab, int cells_dx, int tilex_ty) { // Draw tiles across screen: for (; cells_dx > 0; cells_dx += 8, tilex_ty++, cells_dx -= 0x10000) @@ -509,12 +630,12 @@ static void DrawStripM2(const u8 *nametab, const u8 *coltab, const u8 *pattab, i code = nametab[tilex_ty & 0x1f] << 3; pal = coltab[code]; pack = pattab[code]; - TileNormBgGr(cells_dx, pack, pal); + TileNormBgMg(cells_dx, pack, pal); } } /* Draw a scanline */ -static void DrawDisplayM2(int scanline) +static void DrawDisplayM3(int scanline) { struct PicoVideo *pv = &Pico.video; u8 *nametab, *coltab, *pattab; @@ -537,15 +658,16 @@ static void DrawDisplayM2(int scanline) // tiles if (!(pv->debug_p & PVD_KILL_B)) - DrawStripM2(nametab, coltab, pattab, dx | (cells << 16), tilex | (scanline << 16)); + DrawStripM3(nametab, coltab, pattab, dx | (cells << 16), tilex | (scanline << 16)); // sprites if (!(pv->debug_p & PVD_KILL_S_LO)) DrawSpritesTMS(); } -/* Mode 0 */ -/*========*/ + +/* Mode 0 - Graphics I */ +/*=====================*/ /* Draw the background into a scanline; cells, dx, tilex, ty merged to reduce registers */ static void DrawStripM0(const u8 *nametab, const u8 *coltab, const u8 *pattab, int cells_dx, int tilex_ty) @@ -559,7 +681,7 @@ static void DrawStripM0(const u8 *nametab, const u8 *coltab, const u8 *pattab, i code = nametab[tilex_ty & 0x1f]; pal = coltab[code >> 3]; pack = pattab[code << 3]; - TileNormBgGr(cells_dx, pack, pal); + TileNormBgMg(cells_dx, pack, pal); } } @@ -690,7 +812,9 @@ void PicoLineSMS(int line) BackFill(bgcolor, 0, &Pico.est); // bgcolor is from 2nd palette in mode 4 if (Pico.video.reg[1] & 0x40) { if (Pico.video.reg[0] & 0x04) DrawDisplayM4(line); - else if (Pico.video.reg[0] & 0x02) DrawDisplayM2(line); + else if (Pico.video.reg[0] & 0x02) DrawDisplayM3(line); + else if (Pico.video.reg[1] & 0x08) DrawDisplayM2(line); + else if (Pico.video.reg[1] & 0x10) DrawDisplayM1(line); else DrawDisplayM0(line); } @@ -705,12 +829,14 @@ norender: Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement; } -/* Fixed palette for TMS9918 modes */ +/* Palette for TMS9918 mode, see https://www.smspower.org/Development/Palette */ +// RGB values: #000000 #000000 #21c842 #5edc78 #5455ed #7d76fc #d4524d #42ebf5 +// #fc5554 #ff7978 #d4c154 #e6ce80 #21b03b #c95b5a #cccccc #ffffff static u16 tmspal[32] = { // SMS palette - 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0, - 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, - // TMS palette +// 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0a00, 0x0f00, 0x0005, 0x0ff0, +// 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, + // GG palette 0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4, 0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff, }; -- 2.39.5