From: notaz Date: Tue, 25 Aug 2009 16:25:22 +0000 (+0000) Subject: sms wip: initial graphics support X-Git-Tag: v1.85~288 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=200772b7904a4851c1beff5ea90b233274639ef4;p=picodrive.git sms wip: initial graphics support git-svn-id: file:///home/notaz/opt/svn/PicoDrive@761 be3aeb3a-fb24-0410-a615-afba39da0efa --- diff --git a/pico/debug.c b/pico/debug.c index 4751cf4f..debaa9bc 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -161,22 +161,14 @@ void PDebugShowSpriteStats(unsigned short *screen, int stride) void PDebugShowPalette(unsigned short *screen, int stride) { - unsigned int *spal=(void *)Pico.cram; - unsigned int *dpal=(void *)HighPal; - int x, y, i; + int x, y; - for (i = 0x3f/2; i >= 0; i--) -#ifdef USE_BGR555 - dpal[i] = ((spal[i]&0x000f000f)<< 1)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)<<4); -#else - dpal[i] = ((spal[i]&0x000f000f)<<12)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)>>7); -#endif - for (i = 0x3f; i >= 0; i--) - HighPal[0x40|i] = (unsigned short)((HighPal[i]>>1)&0x738e); - for (i = 0x3f; i >= 0; i--) { - int t=HighPal[i]&0xe71c;t+=0x4208;if(t&0x20)t|=0x1c;if(t&0x800)t|=0x700;if(t&0x10000)t|=0xe000;t&=0xe71c; - HighPal[0x80|i] = (unsigned short)t; - } + Pico.m.dirtyPal = 1; + if (PicoAHW & PAHW_SMS) + PicoDoHighPal555M4(); + else + PicoDoHighPal555(1); + Pico.m.dirtyPal = 1; screen += 16*stride+8; for (y = 0; y < 8*4; y++) @@ -192,8 +184,6 @@ void PDebugShowPalette(unsigned short *screen, int stride) for (y = 0; y < 8*4; y++) for (x = 0; x < 8*16; x++) screen[x + y*stride] = HighPal[(x/8 + (y/8)*16) | 0x80]; - - Pico.m.dirtyPal = 1; } #if defined(DRAW2_OVERRIDE_LINE_WIDTH) diff --git a/pico/draw.c b/pico/draw.c index 9b9ce91c..4acf22f4 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -74,7 +74,6 @@ struct TileStrip // stuff available in asm: #ifdef _ASM_DRAW_C void DrawWindow(int tstart, int tend, int prio, int sh); -void BackFill(int reg7, int sh); void DrawAllSprites(unsigned char *sprited, int prio, int sh); void DrawTilesFromCache(int *hc, int sh, int rlim); void DrawSpritesSHi(unsigned char *sprited); @@ -1140,7 +1139,7 @@ static void DrawAllSprites(unsigned char *sprited, int prio, int sh) // -------------------------------------------- -static void BackFill(int reg7, int sh) +void BackFill(int reg7, int sh) { unsigned int back; @@ -1303,7 +1302,7 @@ static void FinalizeLine8bit(int sh) } } -static void (*FinalizeLine)(int sh) = FinalizeLineBGR444; +static void (*FinalizeLine)(int sh); // -------------------------------------------- diff --git a/pico/mode4.c b/pico/mode4.c new file mode 100644 index 00000000..7062a177 --- /dev/null +++ b/pico/mode4.c @@ -0,0 +1,218 @@ +#include "pico_int.h" + +static void (*FinalizeLineM4)(void); +static int skip_next_line; + +#define PLANAR_PIXEL(x,p) \ + t = pack & (0x80808080 >> p); \ + if (t) { \ + t = ((t >> (7-p)) | (t >> (14-p)) | (t >> (21-p)) | (t >> (28-p))) & 0x0f; \ + pd[x] = pal|t; \ + } + +static int TileNormM4(int sx, int addr, int pal) +{ + unsigned char *pd = HighCol + sx; + unsigned int pack, t; + + pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + if (pack) + { + PLANAR_PIXEL(0, 0) + PLANAR_PIXEL(1, 1) + PLANAR_PIXEL(2, 2) + PLANAR_PIXEL(3, 3) + PLANAR_PIXEL(4, 4) + PLANAR_PIXEL(5, 5) + PLANAR_PIXEL(6, 6) + PLANAR_PIXEL(7, 7) + return 0; + } + + return 1; /* Tile blank */ +} + +static int TileFlipM4(int sx,int addr,int pal) +{ + unsigned char *pd = HighCol + sx; + unsigned int pack, t; + + pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + if (pack) + { + PLANAR_PIXEL(0, 7) + PLANAR_PIXEL(1, 6) + PLANAR_PIXEL(2, 5) + PLANAR_PIXEL(3, 4) + PLANAR_PIXEL(4, 3) + PLANAR_PIXEL(5, 2) + PLANAR_PIXEL(6, 1) + PLANAR_PIXEL(7, 0) + return 0; + } + + return 1; /* Tile blank */ +} + +struct TileStrip +{ + int nametab; // Position in VRAM of name table (for this tile line) + int line; // Line number in pixels 0x000-0x3ff within the virtual tilemap + int hscroll; // Horizontal scroll value in pixels for the line + int xmask; // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap + int *hc; // cache for high tile codes and their positions + int cells; // cells (tiles) to draw (32 col mode doesn't need to update whole 320) +}; + +static void DrawStrip(struct TileStrip *ts, int cellskip) +{ + int tilex,dx,ty,code=0,addr=0,cells; + int oldcode=-1,blank=-1; // The tile we know is blank + int pal=0; + + // Draw tiles across screen: + tilex=((-ts->hscroll)>>3)+cellskip; + ty=(ts->line&7)<<1; // Y-Offset into tile + dx=((ts->hscroll-1)&7)+1; + cells = ts->cells - cellskip; + if (dx != 8) cells++; // have hscroll, need to draw 1 cell more + dx+=cellskip<<3; + + for (; cells > 0; dx+=8,tilex++,cells--) + { + int zero; + + code=Pico.vram[ts->nametab + (tilex & 0x1f)]; + if (code==blank) continue; + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x1ff)<<4; + addr+=ty; + if (code&0x0400) addr^=0xe; // Y-flip + + pal=((code>>7)&0x10); + } + + if (code&0x0200) zero=TileFlipM4(dx,addr,pal); + else zero=TileNormM4(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } +} + +static void DrawLayer(int cellskip, int maxcells) +{ + struct PicoVideo *pvid=&Pico.video; + struct TileStrip ts; + int vscroll; + + ts.cells=maxcells; + + // Find name table: + ts.nametab=(pvid->reg[2]&0x0e) << (10-1); + + // Get horizontal scroll value, will be masked later + ts.hscroll=0;//pvid->reg[8]; + vscroll=0;//pvid->reg[9]; // Get vertical scroll value + + // Find the line in the name table + ts.line=(vscroll+DrawScanline)&0xff; + ts.nametab+=(ts.line>>3) << (6-1); + + DrawStrip(&ts, cellskip); +} + +static void DrawDisplayM4(void) +{ + DrawLayer(0, 32); +} + +void PicoFrameStartMode4(void) +{ + DrawScanline = 0; + skip_next_line = 0; +} + +void PicoLineMode4(int line) +{ + if (skip_next_line > 0) { + skip_next_line--; + return; + } + + DrawScanline = line; + + if (PicoScanBegin != NULL) + skip_next_line = PicoScanBegin(DrawScanline); + + // Draw screen: + BackFill((Pico.video.reg[7] & 0x0f) | 0x10, 0); + if (Pico.video.reg[1] & 0x40) + DrawDisplayM4(); + + if (FinalizeLineM4 != NULL) + FinalizeLineM4(); + + if (PicoScanEnd != NULL) + skip_next_line = PicoScanEnd(DrawScanline); +} + +void PicoDoHighPal555M4(void) +{ + unsigned int *spal=(void *)Pico.cram; + unsigned int *dpal=(void *)HighPal; + unsigned int t; + int i; + + Pico.m.dirtyPal = 0; + + /* cram is always stored as shorts, even though real hardware probably uses bytes */ + for (i = 0x20/2; i > 0; i--, spal++, dpal++) { + t = *spal; +#ifdef USE_BGR555 + t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10); +#else + t = ((t & 0x00030003)<<14) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)>>1); +#endif + t |= t >> 2; + t |= (t >> 4) & 0x08610861; + *dpal = t; + } +} + +static void FinalizeLineRGB555M4(void) +{ + unsigned short *pd=DrawLineDest; + unsigned char *ps=HighCol+8; + unsigned short *pal=HighPal; + int i; + + if (Pico.m.dirtyPal) + PicoDoHighPal555M4(); + + if (!(PicoOpt & POPT_DIS_32C_BORDER)) + pd += 32; + + for (i = 256/4; i > 0; i--) { + *pd++ = pal[*ps++]; + *pd++ = pal[*ps++]; + *pd++ = pal[*ps++]; + *pd++ = pal[*ps++]; + } +} + +void PicoDrawSetColorFormatMode4(int which) +{ + switch (which) + { + case 1: FinalizeLineM4 = FinalizeLineRGB555M4; break; + default:FinalizeLineM4 = NULL; break; + } +#if OVERRIDE_HIGHCOL + if (which) + HighCol = DefHighCol; +#endif +} + diff --git a/pico/pico.h b/pico/pico.h index c6b118c6..68f6143d 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -179,6 +179,9 @@ extern unsigned char *PicoDraw2FB; // buffer for fast renderer in format (8+32 extern unsigned short *PicoCramHigh; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now) extern void (*PicoPrepareCram)(); // prepares PicoCramHigh for renderer to use +// mode4.c +void PicoDrawSetColorFormatMode4(int which); + // sound.c extern int PsndRate,PsndLen; extern short *PsndOut; diff --git a/pico/pico_int.h b/pico/pico_int.h index 9841b183..6aea7de5 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -272,7 +272,7 @@ struct PicoMisc struct Pico { unsigned char ram[0x10000]; // 0x00000 scratch ram - union { + union { // vram is byteswapped for easier reads when drawing unsigned short vram[0x8000]; // 0x10000 unsigned char vramb[0x4000]; // VRAM in SMS mode }; @@ -415,6 +415,7 @@ int CM_compareRun(int cyc, int is_sub); // draw.c PICO_INTERNAL void PicoFrameStart(void); void PicoDrawSync(int to, int blank_last_line); +void BackFill(int reg7, int sh); extern int DrawScanline; #define MAX_LINE_SPRITES 29 extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; @@ -422,6 +423,11 @@ extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; // draw2.c PICO_INTERNAL void PicoFrameFull(); +// mode4.c +void PicoFrameStartMode4(void); +void PicoLineMode4(int line); +void PicoDoHighPal555M4(void); + // memory.c PICO_INTERNAL void PicoInitPc(unsigned int pc); PICO_INTERNAL unsigned int PicoCheckPc(unsigned int pc); diff --git a/pico/sms.c b/pico/sms.c index 5416845c..25f53cb6 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -28,11 +28,11 @@ static void vdp_data_write(unsigned char d) if (pv->type == 3) { Pico.cram[pv->addr & 0x1f] = d; + Pico.m.dirtyPal = 1; } else { Pico.vramb[pv->addr] = d; } pv->addr = (pv->addr + 1) & 0x3fff; - elprintf(EL_ANOMALY, " addr=%04x", pv->addr); pv->pending = 0; } @@ -44,7 +44,7 @@ static void vdp_ctl_write(unsigned char d) if (pv->pending) { if ((d >> 6) == 2) { pv->reg[d & 0x0f] = pv->addr; - elprintf(EL_ANOMALY, " VDP r%02x=%02x", d & 0x0f, pv->addr & 0xff); + elprintf(EL_IO, " VDP r%02x=%02x", d & 0x0f, pv->addr & 0xff); } pv->type = d >> 6; pv->addr &= 0x00ff; @@ -60,7 +60,7 @@ static unsigned char z80_sms_in(unsigned short a) { unsigned char d = 0; - elprintf(EL_ANOMALY, "z80 port %04x read", a); + elprintf(EL_IO, "z80 port %04x read", a); a &= 0xc1; switch (a) { @@ -95,13 +95,13 @@ static unsigned char z80_sms_in(unsigned short a) break; } - elprintf(EL_ANOMALY, "ret = %02x", d); + elprintf(EL_IO, "ret = %02x", d); return d; } static void z80_sms_out(unsigned short a, unsigned char d) { - elprintf(EL_ANOMALY, "z80 port %04x write %02x", a, d); + elprintf(EL_IO, "z80 port %04x write %02x", a, d); a &= 0xc1; switch (a) { @@ -151,15 +151,9 @@ static void write_bank(unsigned short a, unsigned char d) } } -static unsigned char MEMH_FUNC xread(unsigned short a) -{ - elprintf(EL_ANOMALY, "z80 read [%04x]", a); - return Pico.zram[a & 0x1fff]; -} - static void MEMH_FUNC xwrite(unsigned int a, unsigned char d) { - elprintf(EL_ANOMALY, "z80 write [%04x] %02x", a, d); + elprintf(EL_IO, "z80 write [%04x] %02x", a, d); if (a >= 0xc000) Pico.zram[a & 0x1fff] = d; if (a >= 0xfff0) @@ -186,7 +180,7 @@ void PicoMemSetupMS(void) { z80_map_set(z80_read_map, 0x0000, 0xbfff, Pico.rom, 0); z80_map_set(z80_read_map, 0xc000, 0xdfff, Pico.zram, 0); - z80_map_set(z80_read_map, 0xe000, 0xffff, xread, 1); + z80_map_set(z80_read_map, 0xe000, 0xffff, Pico.zram, 0); z80_map_set(z80_write_map, 0x0000, 0xbfff, xwrite, 1); z80_map_set(z80_write_map, 0xc000, 0xdfff, Pico.zram, 0); @@ -215,11 +209,15 @@ void PicoFrameMS(void) int lines_vis = 192; int y; + PicoFrameStartMode4(); + for (y = 0; y < lines; y++) { pv->v_counter = Pico.m.scanline = y; - if (y == lines_vis + 1) { + if (y < lines_vis) + PicoLineMode4(y); + else if (y == lines_vis + 1) { Pico.video.pending_ints |= 1; if (Pico.video.reg[1] & 0x20) { elprintf(EL_INTS, "vint"); @@ -232,6 +230,5 @@ void PicoFrameMS(void) } PsndGetSamplesMS(); - elprintf(EL_ANOMALY, "frame end"); } diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index c608f32f..92e5b74a 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -439,6 +439,7 @@ static void vidResetMode(void) } else if (currentConfig.EmuOpt & EOPT_16BPP) { PicoDrawSetColorFormat(1); + PicoDrawSetColorFormatMode4(1); if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { gp2x_video_changemode(-16); PicoScanBegin = EmuScanBegin16_rot; diff --git a/platform/linux/Makefile b/platform/linux/Makefile index b9254507..be932ed0 100644 --- a/platform/linux/Makefile +++ b/platform/linux/Makefile @@ -34,7 +34,7 @@ endif # Pico OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o \ pico/videoport.o pico/draw2.o pico/draw.o pico/z80if.o pico/patch.o \ - pico/sms.o pico/debug.o + pico/mode4.o pico/sms.o pico/debug.o # Pico - CD OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \ pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \