From 87b0845f3733166b491ae236feb8bc2eb0fca2ec Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 27 Aug 2009 21:44:52 +0000 Subject: [PATCH] more sms wip, better ROM detect, line callback change git-svn-id: file:///home/notaz/opt/svn/PicoDrive@762 be3aeb3a-fb24-0410-a615-afba39da0efa --- pico/cart.c | 105 +++++++++++++------ pico/debug.c | 25 ++++- pico/debug.h | 1 + pico/draw.c | 82 +++++++++------ pico/mode4.c | 197 +++++++++++++++++++++++------------ pico/pico.c | 8 +- pico/pico.h | 6 +- pico/pico_int.h | 2 + pico/sms.c | 60 ++++++++++- platform/common/emu.c | 63 ++++++++--- platform/common/menu.c | 2 +- platform/common/revision.mak | 8 ++ platform/gizmondo/emu.c | 2 - platform/gp2x/Makefile | 9 +- platform/gp2x/emu.c | 7 -- platform/linux/Makefile | 9 +- platform/pandora/emu.c | 2 - platform/psp/emu.c | 4 - platform/uiq3/engine/vid.cpp | 4 +- 19 files changed, 412 insertions(+), 184 deletions(-) create mode 100644 platform/common/revision.mak diff --git a/pico/cart.c b/pico/cart.c index 11484ff..8614a16 100644 --- a/pico/cart.c +++ b/pico/cart.c @@ -71,18 +71,31 @@ static int uncompress2(void *dest, int destLen, void *source, int sourceLen) return inflateEnd(&stream); } +static const char *get_ext(const char *path) +{ + const char *ext; + if (strlen(path) < 4) + return ""; // no ext + + // allow 2 or 3 char extensions for now + ext = path + strlen(path) - 2; + if (ext[-1] != '.') ext--; + if (ext[-1] != '.') + return ""; + return ext; +} + pm_file *pm_open(const char *path) { pm_file *file = NULL; const char *ext; FILE *f; - if (path == NULL) return NULL; - - if (strlen(path) < 5) ext = NULL; // no ext - else ext = path + strlen(path) - 3; + if (path == NULL) + return NULL; - if (ext && strcasecmp(ext, "zip") == 0) + ext = get_ext(path); + if (strcasecmp(ext, "zip") == 0) { struct zipent *zipentry; gzFile gzf = NULL; @@ -90,21 +103,19 @@ pm_file *pm_open(const char *path) int i; zipfile = openzip(path); - if (zipfile != NULL) { /* search for suitable file (right extension or large enough file) */ while ((zipentry = readzip(zipfile)) != NULL) { - if (zipentry->uncompressed_size >= 128*1024) goto found_rom_zip; - if (strlen(zipentry->name) < 5) continue; + ext = get_ext(zipentry->name); - ext = zipentry->name + strlen(zipentry->name) - 2; - if (ext[-1] != '.') ext--; - if (ext[-1] != '.') ext--; + if (zipentry->uncompressed_size >= 32*1024) + goto found_rom_zip; for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++) - if (strcasecmp(ext, rom_exts[i]) == 0) goto found_rom_zip; + if (strcasecmp(ext, rom_exts[i]) == 0) + goto found_rom_zip; } /* zipfile given, but nothing found suitable for us inside */ @@ -115,12 +126,13 @@ found_rom_zip: gzf = zip2gz(zipfile, zipentry); if (gzf == NULL) goto zip_failed; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) goto zip_failed; file->file = zipfile; file->param = gzf; file->size = zipentry->uncompressed_size; file->type = PMT_ZIP; + strncpy(file->ext, ext, sizeof(file->ext) - 1); return file; zip_failed: @@ -132,7 +144,7 @@ zip_failed: return NULL; } } - else if (ext && strcasecmp(ext, "cso") == 0) + else if (strcasecmp(ext, "cso") == 0) { cso_struct *cso = NULL, *tmp = NULL; int size; @@ -179,7 +191,7 @@ zip_failed: cso->fpos_in = ftell(f); cso->fpos_out = 0; cso->block_in_buff = -1; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) goto cso_failed; file->file = f; file->param = cso; @@ -197,7 +209,7 @@ cso_failed: f = fopen(path, "rb"); if (f == NULL) return NULL; - file = malloc(sizeof(*file)); + file = calloc(1, sizeof(*file)); if (file == NULL) { fclose(f); return NULL; @@ -207,6 +219,7 @@ cso_failed: file->param = NULL; file->size = ftell(f); file->type = PMT_UNCOMPRESSED; + strncpy(file->ext, ext, sizeof(file->ext) - 1); fseek(f, 0, SEEK_SET); #ifndef __EPOC32__ // makes things worse on Symbian @@ -421,37 +434,51 @@ static unsigned char *cd_realloc(void *old, int filesize) return rom; } -static unsigned char *PicoCartAlloc(int filesize) +static unsigned char *PicoCartAlloc(int filesize, int is_sms) { int alloc_size; unsigned char *rom; - if (PicoAHW & PAHW_MCD) return cd_realloc(NULL, filesize); + if (PicoAHW & PAHW_MCD) + return cd_realloc(NULL, filesize); + + if (is_sms) { + // make size power of 2 for easier banking handling + int s = 0, tmp = filesize; + while ((tmp >>= 1) != 0) + s++; + if (filesize > (1 << s)) + s++; + alloc_size = 1 << s; + } + else { + // align to 512K for memhandlers + alloc_size = (filesize + 0x7ffff) & ~0x7ffff; + } - alloc_size=filesize+0x7ffff; - if((filesize&0x3fff)==0x200) alloc_size-=0x200; - alloc_size&=~0x7ffff; // use alloc size of multiples of 512K, so that memhandlers could be set up more efficiently - if((filesize&0x3fff)==0x200) alloc_size+=0x200; - else if(alloc_size-filesize < 4) alloc_size+=4; // padding for out-of-bound exec protection + if (alloc_size - filesize < 4) + alloc_size += 4; // padding for out-of-bound exec protection // Allocate space for the rom plus padding - rom=(unsigned char *)malloc(alloc_size); - if(rom) memset(rom+alloc_size-0x80000,0,0x80000); + rom = calloc(alloc_size, 1); return rom; } int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) { - unsigned char *rom=NULL; int size, bytes_read; - if (f==NULL) return 1; + unsigned char *rom; + int size, bytes_read; + + if (f == NULL) + return 1; - size=f->size; + size = f->size; if (size <= 0) return 1; - size=(size+3)&~3; // Round up to a multiple of 4 + size = (size+3)&~3; // Round up to a multiple of 4 // Allocate space for the rom plus padding - rom=PicoCartAlloc(size); - if (rom==NULL) { + rom = PicoCartAlloc(size, is_sms); + if (rom == NULL) { elprintf(EL_STATUS, "out of memory (wanted %i)", size); return 2; } @@ -491,15 +518,25 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) } // Check for SMD: - if (size >= 0x4200 && (size&0x3fff)==0x200 && + if (size >= 0x4200 && (size&0x3fff) == 0x200 && ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) { + elprintf(EL_STATUS, "SMD format detected."); DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD } else Byteswap(rom,size); // Just byteswap } + else + { + if (size >= 0x4200 && (size&0x3fff) == 0x200) { + elprintf(EL_STATUS, "SMD format detected."); + // at least here it's not interleaved + size -= 0x200; + memmove(rom, rom + 0x200, size); + } + } - if (prom) *prom=rom; - if (psize) *psize=size; + if (prom) *prom = rom; + if (psize) *psize = size; return 0; } diff --git a/pico/debug.c b/pico/debug.c index debaa9b..d6b91bd 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -270,11 +270,19 @@ void PDebugShowSprite(unsigned short *screen, int stride, int which) void PDebugDumpMem(void) { - dump_ram(Pico.ram, "dumps/ram.bin"); dump_ram_noswab(Pico.zram, "dumps/zram.bin"); - dump_ram(Pico.vram, "dumps/vram.bin"); dump_ram(Pico.cram, "dumps/cram.bin"); - dump_ram(Pico.vsram,"dumps/vsram.bin"); + + if (PicoAHW & PAHW_SMS) + { + dump_ram_noswab(Pico.vramb, "dumps/vram.bin"); + } + else + { + dump_ram(Pico.ram, "dumps/ram.bin"); + dump_ram(Pico.vram, "dumps/vram.bin"); + dump_ram(Pico.vsram,"dumps/vsram.bin"); + } if (PicoAHW & PAHW_MCD) { @@ -296,6 +304,9 @@ void PDebugZ80Frame(void) { int lines, line_sample; + if (PicoAHW & PAHW_SMS) + return; + if (Pico.m.pal) { lines = 312; line_sample = 68; @@ -332,3 +343,11 @@ void PDebugZ80Frame(void) timers_cycle(); } +void PDebugCPUStep(void) +{ + if (PicoAHW & PAHW_SMS) + z80_run(1); + else + SekStepM68k(); +} + diff --git a/pico/debug.h b/pico/debug.h index be819ee..d2ac82c 100644 --- a/pico/debug.h +++ b/pico/debug.h @@ -6,4 +6,5 @@ void PDebugShowPalette(unsigned short *screen, int stride); void PDebugShowSprite(unsigned short *screen, int stride, int which); void PDebugDumpMem(void); void PDebugZ80Frame(void); +void PDebugCPUStep(void); diff --git a/pico/draw.c b/pico/draw.c index 4acf22f..747f428 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -40,7 +40,7 @@ unsigned char *HighCol=DefHighCol; #else unsigned char HighCol[8+320+8]; #endif -unsigned short DefOutBuff[320*2]; +static unsigned int DefOutBuff[320*2/2]; void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to static int HighCacheA[41+1]; // caches for high layers @@ -1269,7 +1269,7 @@ static void FinalizeLine8bit(int sh) int len, rs = rendstatus; static int dirty_count; - if (!sh && Pico.m.dirtyPal == 1 && DrawScanline < 222) + if (!sh && Pico.m.dirtyPal == 1) { // a hack for mid-frame palette changes if (!(rs & PDRAW_SONIC_MODE)) @@ -1306,22 +1306,6 @@ static void (*FinalizeLine)(int sh); // -------------------------------------------- -static void DrawBlankedLine(void) -{ - int sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight? - - if (PicoScanBegin != NULL) - PicoScanBegin(DrawScanline); - - BackFill(Pico.video.reg[7], sh); - - if (FinalizeLine != NULL) - FinalizeLine(sh); - - if (PicoScanEnd != NULL) - PicoScanEnd(DrawScanline); -} - static int DrawDisplay(int sh) { unsigned char *sprited = &HighLnSpr[DrawScanline][0]; @@ -1420,23 +1404,46 @@ PICO_INTERNAL void PicoFrameStart(void) rendstatus = 0; if ((Pico.video.reg[12]&6) == 6) rendstatus |= PDRAW_INTERLACE; // interlace mode + if (Pico.video.reg[1] & 8) + rendstatus |= PDRAW_240LINES; - if (Pico.m.dirtyPal) Pico.m.dirtyPal = 2; // reset dirty if needed + if (Pico.m.dirtyPal) + Pico.m.dirtyPal = 2; // reset dirty if needed DrawScanline=0; PrepareSprites(1); skip_next_line=0; } -static void PicoLine(void) +static void DrawBlankedLine(int line, int offs) +{ + int sh = (Pico.video.reg[0xC]&8)>>3; // shadow/hilight? + + if (PicoScanBegin != NULL) + PicoScanBegin(line + offs); + + BackFill(Pico.video.reg[7], sh); + + if (FinalizeLine != NULL) + FinalizeLine(sh); + + if (PicoScanEnd != NULL) + PicoScanEnd(line + offs); +} + +static void PicoLine(int line, int offs) { int sh; - if (skip_next_line>0) { skip_next_line--; return; } // skip rendering lines + if (skip_next_line > 0) { + skip_next_line--; + return; + } sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight? + DrawScanline = line; if (PicoScanBegin != NULL) - skip_next_line = PicoScanBegin(DrawScanline); + skip_next_line = PicoScanBegin(line + offs); // Draw screen: BackFill(Pico.video.reg[7], sh); @@ -1447,31 +1454,40 @@ static void PicoLine(void) FinalizeLine(sh); if (PicoScanEnd != NULL) - skip_next_line = PicoScanEnd(DrawScanline); + skip_next_line = PicoScanEnd(line + offs); } void PicoDrawSync(int to, int blank_last_line) { - for (; DrawScanline < to; DrawScanline++) + int line, offs = 0; + + if (!(rendstatus & PDRAW_240LINES)) + offs = 8; + + for (line = DrawScanline; line < to; line++) { #if !CAN_HANDLE_240_LINES - if (DrawScanline >= 224) break; + if (line >= 224) break; #endif - PicoLine(); + PicoLine(line, offs); } #if !CAN_HANDLE_240_LINES - if (DrawScanline >= 224) { DrawScanline = 240; return; } + if (line >= 224) { + DrawScanline = 240; + return; + } #endif // last line - if (DrawScanline <= to) + if (line <= to) { if (blank_last_line) - DrawBlankedLine(); - else PicoLine(); - DrawScanline++; + DrawBlankedLine(line, offs); + else PicoLine(line, offs); + line++; } + DrawScanline = line; } void PicoDrawSetColorFormat(int which) @@ -1483,8 +1499,10 @@ void PicoDrawSetColorFormat(int which) case 0: FinalizeLine = FinalizeLineBGR444; break; default:FinalizeLine = NULL; break; } + PicoDrawSetColorFormatMode4(which); #if OVERRIDE_HIGHCOL - if (which) HighCol=DefHighCol; + if (which) + HighCol=DefHighCol; #endif } diff --git a/pico/mode4.c b/pico/mode4.c index 7062a17..095250f 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -1,7 +1,16 @@ +/* + * TODO: + * - TMS9918 modes? + * - gg mode? + * - column scroll (reg 0 bit7) + * - 224/240 line modes + * - doubled sprites + */ #include "pico_int.h" static void (*FinalizeLineM4)(void); static int skip_next_line; +static int screen_offset; #define PLANAR_PIXEL(x,p) \ t = pack & (0x80808080 >> p); \ @@ -54,85 +63,145 @@ static int TileFlipM4(int sx,int addr,int pal) return 1; /* Tile blank */ } -struct TileStrip +static void draw_sprites(int scanline) { - 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) + struct PicoVideo *pv = &Pico.video; + unsigned int sprites_addr[8]; + unsigned int sprites_x[8]; + unsigned char *sat; + int xoff = 8; // relative to HighCol, which is (screen - 8) + int sprite_base, addr_mask; + int i, s, h; + + if (pv->reg[0] & 8) + xoff = 0; + + sat = (unsigned char *)Pico.vram + ((pv->reg[5] & 0x7e) << 7); + if (pv->reg[1] & 2) { + addr_mask = 0xfe; h = 16; + } else { + addr_mask = 0xff; h = 8; + } + sprite_base = (pv->reg[6] & 4) << (13-2-1); + + for (i = s = 0; i < 64 && s < 8; i++) + { + int y; + y = sat[i] + 1; + if (y == 0xd1) + break; + if (y + h <= scanline || scanline < y) + continue; // not on this line + + sprites_x[s] = xoff + sat[0x80 + i*2]; + sprites_addr[s] = sprite_base + ((sat[0x80 + i*2 + 1] & addr_mask) << (5-1)) + + ((scanline - y) << (2-1)); + s++; + } + + // now draw all sprites backwards + for (--s; s >= 0; s--) + TileNormM4(sprites_x[s], sprites_addr[s], 0x10); +} + +// tilex_ty_prio merged to reduce register pressure +static void draw_strip(const unsigned short *nametab, int dx, int cells, int tilex_ty_prio) { - int tilex,dx,ty,code=0,addr=0,cells; - int oldcode=-1,blank=-1; // The tile we know is blank - int pal=0; + int oldcode = -1, blank = -1; // The tile we know is blank + int addr = 0, 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--) + for (; cells > 0; dx += 8, tilex_ty_prio++, cells--) { - int zero; + int code, zero; - code=Pico.vram[ts->nametab + (tilex & 0x1f)]; - if (code==blank) continue; + code = nametab[tilex_ty_prio & 0x1f]; + if (code == blank) + continue; + if ((code ^ tilex_ty_prio) & 0x1000) // priority differs? + continue; - if (code!=oldcode) { + if (code != oldcode) { oldcode = code; // Get tile address/2: - addr=(code&0x1ff)<<4; - addr+=ty; - if (code&0x0400) addr^=0xe; // Y-flip + addr = (code & 0x1ff) << 4; + addr += tilex_ty_prio >> 16; + if (code & 0x0400) + addr ^= 0xe; // Y-flip - pal=((code>>7)&0x10); + pal = (code>>7) & 0x10; } - if (code&0x0200) zero=TileFlipM4(dx,addr,pal); - else zero=TileNormM4(dx,addr,pal); + 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 + if (zero) + blank = code; // We know this tile is blank now } } -static void DrawLayer(int cellskip, int maxcells) +static void DrawDisplayM4(int scanline) { - 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 + struct PicoVideo *pv = &Pico.video; + unsigned short *nametab; + int line, tilex, dx, ty, cells; + int cellskip = 0; // XXX + int maxcells = 32; // Find the line in the name table - ts.line=(vscroll+DrawScanline)&0xff; - ts.nametab+=(ts.line>>3) << (6-1); + line = pv->reg[9] + scanline; // vscroll + scanline + if (line >= 224) + line -= 224; - DrawStrip(&ts, cellskip); -} - -static void DrawDisplayM4(void) -{ - DrawLayer(0, 32); + // Find name table: + nametab = Pico.vram; + nametab += (pv->reg[2] & 0x0e) << (10-1); + nametab += (line>>3) << (6-1); + + dx = pv->reg[8]; // hscroll + if (scanline < 16 && (pv->reg[0] & 0x40)) + dx = 0; // hscroll disabled for top 2 rows + + tilex = ((-dx >> 3) + cellskip) & 0x1f; + ty = (line & 7) << 1; // Y-Offset into tile + cells = maxcells - cellskip; + + dx = ((dx - 1) & 7) + 1; + if (dx != 8) + cells++; // have hscroll, need to draw 1 cell more + dx += cellskip << 3; + + // low priority tiles + if (PicoDrawMask & PDRAW_LAYERB_ON) + draw_strip(nametab, dx, cells, tilex | 0x0000 | (ty << 16)); + + // sprites + if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) + draw_sprites(scanline); + + // high priority tiles (use virtual layer switch just for fun) + if (PicoDrawMask & PDRAW_LAYERA_ON) + draw_strip(nametab, dx, cells, tilex | 0x1000 | (ty << 16)); + + if (pv->reg[0] & 0x20) + // first column masked + ((int *)HighCol)[2] = ((int *)HighCol)[3] = 0xe0e0e0e0; } void PicoFrameStartMode4(void) { - DrawScanline = 0; skip_next_line = 0; + screen_offset = 24; + rendstatus = PDRAW_192LINES; + if ((Pico.video.reg[0] & 6) == 6 && (Pico.video.reg[1] & 0x18)) { + rendstatus &= ~PDRAW_192LINES; + if (Pico.video.reg[1] & 0x08) { + screen_offset = 0; + rendstatus |= PDRAW_240LINES; + } + else // it's 224 lines + screen_offset = 8; + } } void PicoLineMode4(int line) @@ -142,21 +211,19 @@ void PicoLineMode4(int line) return; } - DrawScanline = line; - if (PicoScanBegin != NULL) - skip_next_line = PicoScanBegin(DrawScanline); + skip_next_line = PicoScanBegin(line + screen_offset); // Draw screen: - BackFill((Pico.video.reg[7] & 0x0f) | 0x10, 0); + BackFill(Pico.video.reg[7] & 0x0f, 0); if (Pico.video.reg[1] & 0x40) - DrawDisplayM4(); + DrawDisplayM4(line); if (FinalizeLineM4 != NULL) FinalizeLineM4(); if (PicoScanEnd != NULL) - skip_next_line = PicoScanEnd(DrawScanline); + skip_next_line = PicoScanEnd(line + screen_offset); } void PicoDoHighPal555M4(void) @@ -203,16 +270,18 @@ static void FinalizeLineRGB555M4(void) } } +static void FinalizeLine8bitM4(void) +{ + memcpy32(DrawLineDest, (int *)(HighCol+8), 256/4); +} + void PicoDrawSetColorFormatMode4(int which) { switch (which) { + case 2: FinalizeLineM4 = FinalizeLine8bitM4; break; case 1: FinalizeLineM4 = FinalizeLineRGB555M4; break; default:FinalizeLineM4 = NULL; break; } -#if OVERRIDE_HIGHCOL - if (which) - HighCol = DefHighCol; -#endif } diff --git a/pico/pico.c b/pico/pico.c index 00184e6..c919507 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -312,8 +312,12 @@ void PicoFrame(void) void PicoFrameDrawOnly(void) { - PicoFrameStart(); - PicoDrawSync(223, 0); + if (!(PicoAHW & PAHW_SMS)) { + PicoFrameStart(); + PicoDrawSync(223, 0); + } else { + PicoFrameDrawOnlyMS(); + } } void PicoGetInternal(pint_t which, pint_ret_t *r) diff --git a/pico/pico.h b/pico/pico.h index 68f6143..7436a60 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -129,6 +129,7 @@ typedef struct void *param; /* additional file related field */ unsigned int size; /* size */ pm_type type; + char ext[4]; } pm_file; pm_file *pm_open(const char *path); size_t pm_read(void *ptr, size_t bytes, pm_file *stream); @@ -170,6 +171,8 @@ extern int PicoDrawMask; #define PDRAW_SONIC_MODE (1<<5) // mid-frame palette changes for 8bit renderer #define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3) #define PDRAW_SHHI_DONE (1<<7) // layer sh/hi already processed +#define PDRAW_240LINES (1<<8) // 240 line display (224 if not set) +#define PDRAW_192LINES (1<<9) // 192 line display (for SMS games) extern int rendstatus; extern unsigned short HighPal[0x100]; @@ -179,9 +182,6 @@ 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 6aea7de..4a4418e 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -427,6 +427,7 @@ PICO_INTERNAL void PicoFrameFull(); void PicoFrameStartMode4(void); void PicoLineMode4(int line); void PicoDoHighPal555M4(void); +void PicoDrawSetColorFormatMode4(int which); // memory.c PICO_INTERNAL void PicoInitPc(unsigned int pc); @@ -567,6 +568,7 @@ void PicoPowerMS(void); void PicoResetMS(void); void PicoMemSetupMS(void); void PicoFrameMS(void); +void PicoFrameDrawOnlyMS(void); // emulation event logging #ifndef EL_LOGMASK diff --git a/pico/sms.c b/pico/sms.c index 25f53cb..ba9be50 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -1,3 +1,13 @@ +/* + * TODO: + * - start in a state as if BIOS ran + * - remaining status flags (OVR/COL) + * - RAM support in mapper + * - region support + * - Pause button (NMI) + * - SN76496 DAC-like usage + * - H counter + */ #include "pico_int.h" #include "sound/sn76496.h" @@ -71,10 +81,12 @@ static unsigned char z80_sms_in(unsigned short a) case 0x40: /* V counter */ d = Pico.video.v_counter; + elprintf(EL_HVCNT, "V counter read: %02x", d); break; case 0x41: /* H counter */ d = Pico.m.rotate++; + elprintf(EL_HVCNT, "H counter read: %02x", d); break; case 0x80: @@ -125,24 +137,28 @@ static void z80_sms_out(unsigned short a, unsigned char d) } } +static int bank_mask; + static void write_bank(unsigned short a, unsigned char d) { - d &= 0x3f; // XXX switch (a & 0x0f) { case 0x0c: + elprintf(EL_STATUS|EL_ANOMALY, "%02x written to control reg!", d); break; case 0x0d: if (d != 0) elprintf(EL_STATUS|EL_ANOMALY, "bank0 changed to %d!", d); break; case 0x0e: + d &= bank_mask; z80_map_set(z80_read_map, 0x4000, 0x7fff, Pico.rom + (d << 14), 0); #ifdef _USE_CZ80 Cz80_Set_Fetch(&CZ80, 0x4000, 0x7fff, (UINT32)Pico.rom + (d << 14)); #endif break; case 0x0f: + d &= bank_mask; z80_map_set(z80_read_map, 0x8000, 0xbfff, Pico.rom + (d << 14), 0); #ifdef _USE_CZ80 Cz80_Set_Fetch(&CZ80, 0x8000, 0xbfff, (UINT32)Pico.rom + (d << 14)); @@ -168,11 +184,23 @@ void PicoResetMS(void) void PicoPowerMS(void) { + int s, tmp; + memset(&Pico.ram,0,(unsigned int)&Pico.rom-(unsigned int)&Pico.ram); memset(&Pico.video,0,sizeof(Pico.video)); memset(&Pico.m,0,sizeof(Pico.m)); Pico.m.pal = 0; + // calculate a mask for bank writes. + // ROM loader has aligned the size for us, so this is safe. + s = 0; tmp = Pico.romsize; + while ((tmp >>= 1) != 0) + s++; + if (Pico.romsize > (1 << s)) + s++; + tmp = 1 << s; + bank_mask = (tmp - 1) >> 14; + PicoReset(); } @@ -207,9 +235,11 @@ void PicoFrameMS(void) int cycles_line = is_pal ? 58020 : 58293; /* (226.6 : 227.7) * 256 */ int cycles_done = 0, cycles_aim = 0; int lines_vis = 192; + int hint; // Hint counter int y; PicoFrameStartMode4(); + hint = pv->reg[0x0a]; for (y = 0; y < lines; y++) { @@ -217,9 +247,22 @@ void PicoFrameMS(void) if (y < lines_vis) PicoLineMode4(y); + + if (y <= lines_vis) + { + if (--hint < 0) + { + hint = pv->reg[0x0a]; + pv->pending_ints |= 2; + if (pv->reg[0] & 0x10) { + elprintf(EL_INTS, "hint"); + z80_int(); + } + } + } else if (y == lines_vis + 1) { - Pico.video.pending_ints |= 1; - if (Pico.video.reg[1] & 0x20) { + pv->pending_ints |= 1; + if (pv->reg[1] & 0x20) { elprintf(EL_INTS, "vint"); z80_int(); } @@ -232,3 +275,14 @@ void PicoFrameMS(void) PsndGetSamplesMS(); } +void PicoFrameDrawOnlyMS(void) +{ + int lines_vis = 192; + int y; + + PicoFrameStartMode4(); + + for (y = 0; y < lines_vis; y++) + PicoLineMode4(y); +} + diff --git a/platform/common/emu.c b/platform/common/emu.c index 1cecc39..aca54be 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -245,8 +245,11 @@ static int emu_cd_check(int *pregion, const char *fname_in) static int detect_media(const char *fname) { static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 }; + static const char *sms_exts[] = { "sms", "gg", "sg" }; + static const char *md_exts[] = { "gen", "bin", "smd" }; + char buff0[32], buff[32]; + unsigned short *d16; pm_file *pmf; - char buff[32]; char ext[5]; int i; @@ -264,34 +267,69 @@ static int detect_media(const char *fname) if (pmf == NULL) return PM_BAD; - if (pm_read(buff, 32, pmf) != 32) { + if (pm_read(buff0, 32, pmf) != 32) { pm_close(pmf); return PM_BAD; } - if (strncasecmp("SEGADISCSYSTEM", buff + 0x00, 14) == 0 || - strncasecmp("SEGADISCSYSTEM", buff + 0x10, 14) == 0) { + if (strncasecmp("SEGADISCSYSTEM", buff0 + 0x00, 14) == 0 || + strncasecmp("SEGADISCSYSTEM", buff0 + 0x10, 14) == 0) { pm_close(pmf); return PM_CD; } + /* check for SMD evil */ + if (pmf->size >= 0x4200 && (pmf->size & 0x3fff) == 0x200) { + if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200 && + pm_read(buff, 16, pmf) == 16 && + strncmp("TMR SEGA", buff, 8) == 0) + goto looks_like_sms; + + /* could parse further but don't bother */ + goto extension_check; + } + + /* MD header? Act as TMSS BIOS here */ + if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100 && pm_read(buff, 16, pmf) == 16) { + if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0) + goto looks_like_md; + } + for (i = 0; i < array_size(sms_offsets); i++) { if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i]) - goto not_mark3; /* actually it could be but can't be detected */ + continue; if (pm_read(buff, 16, pmf) != 16) - goto not_mark3; + continue; - if (strncasecmp("TMR SEGA", buff, 8) == 0) { - pm_close(pmf); - return PM_MARK3; - } + if (strncmp("TMR SEGA", buff, 8) == 0) + goto looks_like_sms; + } + +extension_check: + /* probably some headerless thing. Maybe check the extension after all. */ + for (i = 0; i < array_size(md_exts); i++) + if (strcasecmp(pmf->ext, md_exts[i]) == 0) + goto looks_like_md; + + for (i = 0; i < array_size(sms_exts); i++) + if (strcasecmp(pmf->ext, sms_exts[i]) == 0) + goto looks_like_sms; + + /* If everything else fails, make a guess on the reset vector */ + d16 = (unsigned short *)(buff0 + 4); + if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= pmf->size) { + lprintf("bad MD reset vector, assuming SMS\n"); + goto looks_like_sms; } -not_mark3: +looks_like_md: pm_close(pmf); - /* the main emu function is to emulate MD, so assume MD */ return PM_MD_CART; + +looks_like_sms: + pm_close(pmf); + return PM_MARK3; } static int extract_text(char *dest, const unsigned char *src, int len, int swab) @@ -450,6 +488,7 @@ int emu_reload_rom(char *rom_fname) shutdown_MCD(); PicoPatchUnload(); + PicoAHW = 0; if (media_type == PM_CD) { diff --git a/platform/common/menu.c b/platform/common/menu.c index dff1b39..08117df 100644 --- a/platform/common/menu.c +++ b/platform/common/menu.c @@ -1803,7 +1803,7 @@ static void debug_menu_loop(void) { case 0: if (inp & PBTN_MOK) - SekStepM68k(); + PDebugCPUStep(); if (inp & PBTN_MA3) { while (inp & PBTN_MA3) inp = in_menu_wait_any(-1); diff --git a/platform/common/revision.mak b/platform/common/revision.mak new file mode 100644 index 0000000..03093e3 --- /dev/null +++ b/platform/common/revision.mak @@ -0,0 +1,8 @@ +platform/common/menu.o : revision.h + +revision.h: FORCE + @echo "#define REVISION \"`svn info -r HEAD | grep Revision | cut -c 11-`\"" > /tmp/r.tmp + @diff -q $@ /tmp/r.tmp > /dev/null 2>&1 || mv -f /tmp/r.tmp $@ + +FORCE: + diff --git a/platform/gizmondo/emu.c b/platform/gizmondo/emu.c index fea424f..b8b1068 100644 --- a/platform/gizmondo/emu.c +++ b/platform/gizmondo/emu.c @@ -103,7 +103,6 @@ void pemu_prep_defconfig(void) static int EmuScanBegin16(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; DrawLineDest = (unsigned short *) giz_screen + 321 * num; if ((currentConfig.EmuOpt&0x4000) && (num&1) == 0) // (Pico.m.frame_count&1)) @@ -115,7 +114,6 @@ static int EmuScanBegin16(unsigned int num) static int EmuScanBegin8(unsigned int num) { // draw like the fast renderer - if (!(Pico.video.reg[1]&8)) num += 8; HighCol = gfx_buffer + 328 * num; return 0; diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index ac79354..92e5d97 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -65,7 +65,7 @@ ifeq "$(amalgamate)" "1" OBJS += ../../picoAll.o else OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o pico/z80if.o \ - pico/videoport.o pico/draw2.o pico/draw.o pico/patch.o pico/debug.o + pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o pico/patch.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 \ @@ -120,12 +120,7 @@ DIRS = platform platform/gp2x platform/linux platform/common pico pico/cd pico/p all: mkdirs PicoDrive include ../common/common_arm.mak - -platform/common/menu.o : revision.h - -revision.h: - @echo "#define REVISION \"`svn info | grep Revision | cut -c 11-`\"" > /tmp/r.tmp - @diff -q $@ /tmp/r.tmp > /dev/null 2>&1 || mv -f /tmp/r.tmp $@ +include ../common/revision.mak # partial linking helps profiled builds due to section merging PicoDrive.o : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 92e5b74..dd4b686 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -220,7 +220,6 @@ static void draw_pico_ptr(void) static int EmuScanBegin16(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; DrawLineDest = (unsigned short *) g_screen_ptr + g_screen_width * num; return 0; @@ -228,7 +227,6 @@ static int EmuScanBegin16(unsigned int num) static int EmuScanBegin8(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; DrawLineDest = (unsigned char *) g_screen_ptr + g_screen_width * num; return 0; @@ -247,8 +245,6 @@ static int EmuScanEnd16_rot(unsigned int num) { if ((num & 3) != 3) return 0; - if (!(Pico.video.reg[1] & 8)) - num += 8; rotated_blit16(g_screen_ptr, rot_buff, num + 1, !(Pico.video.reg[12] & 1) && !(PicoOpt & POPT_EN_SOFTSCALE)); return 0; @@ -264,8 +260,6 @@ static int EmuScanEnd8_rot(unsigned int num) { if ((num & 3) != 3) return 0; - if (!(Pico.video.reg[1] & 8)) - num += 8; rotated_blit8(g_screen_ptr, rot_buff, num + 1, !(Pico.video.reg[12] & 1)); return 0; @@ -439,7 +433,6 @@ 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 be932ed..033d3bd 100644 --- a/platform/linux/Makefile +++ b/platform/linux/Makefile @@ -97,16 +97,13 @@ PicoDrive : $(OBJS) ../common/helix/helix_mp3_x86.a $(CC) $(CFLAGS) $^ $(LDFLAGS) -lm -lpng -Wl,-Map=PicoDrive.map -o $@ mkdirs: - mkdir -p $(DIRS) + @mkdir -p $(DIRS) + +include ../common/revision.mak pico/carthw/svp/compiler.o : ../../pico/carthw/svp/gen_arm.c pico/pico.o pico/cd/pico.o : ../../pico/pico_cmn.c ../../pico/pico_int.h pico/memory.o pico/cd/memory.o : ../../pico/memory_cmn.c ../../pico/pico_int.h -platform/common/menu.o : revision.h - -revision.h: - @echo "#define REVISION \"`svn info | grep Revision | cut -c 11-`\"" > /tmp/r.tmp - @diff -q $@ /tmp/r.tmp > /dev/null 2>&1 || mv -f /tmp/r.tmp $@ ../../cpu/musashi/m68kops.c : @make -C ../../cpu/musashi diff --git a/platform/pandora/emu.c b/platform/pandora/emu.c index a9a2119..3fbda4a 100644 --- a/platform/pandora/emu.c +++ b/platform/pandora/emu.c @@ -186,7 +186,6 @@ static void draw_pico_ptr(void) static int EmuScanBegin16(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; DrawLineDest = (unsigned short *)g_screen_ptr + num*800 + 800/2 - 320/2; //int w = (Pico.video.reg[12]&1) ? 320 : 256; //DrawLineDest = (unsigned short *)g_screen_ptr + num*w; @@ -204,7 +203,6 @@ static int EmuScanEnd16(unsigned int num) int sh = Pico.video.reg[0xC]&8; int len, mask = 0xff; - if (!(Pico.video.reg[1]&8)) num += 8; pd=(unsigned short *)g_screen_ptr + num*800*2 + 800/2 - 320*2/2; if (Pico.m.dirtyPal) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index e0e1ca1..5eca789 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -261,8 +261,6 @@ static void EmuScanPrepare(void) static int EmuScanSlowBegin(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; - if (!dynamic_palette) HighCol = (unsigned char *)VRAM_CACHED_STUFF + num * 512 + 8; @@ -271,8 +269,6 @@ static int EmuScanSlowBegin(unsigned int num) static int EmuScanSlowEnd(unsigned int num) { - if (!(Pico.video.reg[1]&8)) num += 8; - if (Pico.m.dirtyPal) { if (!dynamic_palette) { do_slowmode_lines(num); diff --git a/platform/uiq3/engine/vid.cpp b/platform/uiq3/engine/vid.cpp index b23a531..d004bdf 100644 --- a/platform/uiq3/engine/vid.cpp +++ b/platform/uiq3/engine/vid.cpp @@ -92,7 +92,7 @@ static const unsigned long mask_numbers[] = { static int EmuScanBegin8(unsigned int num) { - DrawLineDest = PicoDraw2FB + 328*num + 328*8 + 8; + DrawLineDest = PicoDraw2FB + 328*num + 8; return 0; } @@ -105,7 +105,7 @@ static int EmuScanEndFit0(unsigned int num) static int u = 0, num2 = 0; if(!num) u = num2 = 0; - DrawLineDest = PicoDraw2FB + 328*(++num2) + 328*8 + 8; + DrawLineDest = PicoDraw2FB + 328*(++num2) + 8; u += 6666; -- 2.39.2