more sms wip, better ROM detect, line callback change
authornotaz <notasas@gmail.com>
Thu, 27 Aug 2009 21:44:52 +0000 (21:44 +0000)
committernotaz <notasas@gmail.com>
Thu, 27 Aug 2009 21:44:52 +0000 (21:44 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@762 be3aeb3a-fb24-0410-a615-afba39da0efa

19 files changed:
pico/cart.c
pico/debug.c
pico/debug.h
pico/draw.c
pico/mode4.c
pico/pico.c
pico/pico.h
pico/pico_int.h
pico/sms.c
platform/common/emu.c
platform/common/menu.c
platform/common/revision.mak [new file with mode: 0644]
platform/gizmondo/emu.c
platform/gp2x/Makefile
platform/gp2x/emu.c
platform/linux/Makefile
platform/pandora/emu.c
platform/psp/emu.c
platform/uiq3/engine/vid.cpp

index 11484ff..8614a16 100644 (file)
@@ -71,18 +71,31 @@ static int uncompress2(void *dest, int destLen, void *source, int sourceLen)
     return inflateEnd(&stream);\r
 }\r
 \r
+static const char *get_ext(const char *path)\r
+{\r
+  const char *ext;\r
+  if (strlen(path) < 4)\r
+    return ""; // no ext\r
+\r
+  // allow 2 or 3 char extensions for now\r
+  ext = path + strlen(path) - 2;\r
+  if (ext[-1] != '.') ext--;\r
+  if (ext[-1] != '.')\r
+    return "";\r
+  return ext;\r
+}\r
+\r
 pm_file *pm_open(const char *path)\r
 {\r
   pm_file *file = NULL;\r
   const char *ext;\r
   FILE *f;\r
 \r
-  if (path == NULL) return NULL;\r
-\r
-  if (strlen(path) < 5) ext = NULL; // no ext\r
-  else ext = path + strlen(path) - 3;\r
+  if (path == NULL)\r
+    return NULL;\r
 \r
-  if (ext && strcasecmp(ext, "zip") == 0)\r
+  ext = get_ext(path);\r
+  if (strcasecmp(ext, "zip") == 0)\r
   {\r
     struct zipent *zipentry;\r
     gzFile gzf = NULL;\r
@@ -90,21 +103,19 @@ pm_file *pm_open(const char *path)
     int i;\r
 \r
     zipfile = openzip(path);\r
-\r
     if (zipfile != NULL)\r
     {\r
       /* search for suitable file (right extension or large enough file) */\r
       while ((zipentry = readzip(zipfile)) != NULL)\r
       {\r
-        if (zipentry->uncompressed_size >= 128*1024) goto found_rom_zip;\r
-        if (strlen(zipentry->name) < 5) continue;\r
+        ext = get_ext(zipentry->name);\r
 \r
-        ext = zipentry->name + strlen(zipentry->name) - 2;\r
-        if (ext[-1] != '.') ext--;\r
-        if (ext[-1] != '.') ext--;\r
+        if (zipentry->uncompressed_size >= 32*1024)\r
+          goto found_rom_zip;\r
 \r
         for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++)\r
-          if (strcasecmp(ext, rom_exts[i]) == 0) goto found_rom_zip;\r
+          if (strcasecmp(ext, rom_exts[i]) == 0)\r
+            goto found_rom_zip;\r
       }\r
 \r
       /* zipfile given, but nothing found suitable for us inside */\r
@@ -115,12 +126,13 @@ found_rom_zip:
       gzf = zip2gz(zipfile, zipentry);\r
       if (gzf == NULL)  goto zip_failed;\r
 \r
-      file = malloc(sizeof(*file));\r
+      file = calloc(1, sizeof(*file));\r
       if (file == NULL) goto zip_failed;\r
       file->file  = zipfile;\r
       file->param = gzf;\r
       file->size  = zipentry->uncompressed_size;\r
       file->type  = PMT_ZIP;\r
+      strncpy(file->ext, ext, sizeof(file->ext) - 1);\r
       return file;\r
 \r
 zip_failed:\r
@@ -132,7 +144,7 @@ zip_failed:
       return NULL;\r
     }\r
   }\r
-  else if (ext && strcasecmp(ext, "cso") == 0)\r
+  else if (strcasecmp(ext, "cso") == 0)\r
   {\r
     cso_struct *cso = NULL, *tmp = NULL;\r
     int size;\r
@@ -179,7 +191,7 @@ zip_failed:
     cso->fpos_in = ftell(f);\r
     cso->fpos_out = 0;\r
     cso->block_in_buff = -1;\r
-    file = malloc(sizeof(*file));\r
+    file = calloc(1, sizeof(*file));\r
     if (file == NULL) goto cso_failed;\r
     file->file  = f;\r
     file->param = cso;\r
@@ -197,7 +209,7 @@ cso_failed:
   f = fopen(path, "rb");\r
   if (f == NULL) return NULL;\r
 \r
-  file = malloc(sizeof(*file));\r
+  file = calloc(1, sizeof(*file));\r
   if (file == NULL) {\r
     fclose(f);\r
     return NULL;\r
@@ -207,6 +219,7 @@ cso_failed:
   file->param = NULL;\r
   file->size  = ftell(f);\r
   file->type  = PMT_UNCOMPRESSED;\r
+  strncpy(file->ext, ext, sizeof(file->ext) - 1);\r
   fseek(f, 0, SEEK_SET);\r
 \r
 #ifndef __EPOC32__ // makes things worse on Symbian\r
@@ -421,37 +434,51 @@ static unsigned char *cd_realloc(void *old, int filesize)
   return rom;\r
 }\r
 \r
-static unsigned char *PicoCartAlloc(int filesize)\r
+static unsigned char *PicoCartAlloc(int filesize, int is_sms)\r
 {\r
   int alloc_size;\r
   unsigned char *rom;\r
 \r
-  if (PicoAHW & PAHW_MCD) return cd_realloc(NULL, filesize);\r
+  if (PicoAHW & PAHW_MCD)\r
+    return cd_realloc(NULL, filesize);\r
+\r
+  if (is_sms) {\r
+    // make size power of 2 for easier banking handling\r
+    int s = 0, tmp = filesize;\r
+    while ((tmp >>= 1) != 0)\r
+      s++;\r
+    if (filesize > (1 << s))\r
+      s++;\r
+    alloc_size = 1 << s;\r
+  }\r
+  else {\r
+    // align to 512K for memhandlers\r
+    alloc_size = (filesize + 0x7ffff) & ~0x7ffff;\r
+  }\r
 \r
-  alloc_size=filesize+0x7ffff;\r
-  if((filesize&0x3fff)==0x200) alloc_size-=0x200;\r
-  alloc_size&=~0x7ffff; // use alloc size of multiples of 512K, so that memhandlers could be set up more efficiently\r
-  if((filesize&0x3fff)==0x200) alloc_size+=0x200;\r
-  else if(alloc_size-filesize < 4) alloc_size+=4; // padding for out-of-bound exec protection\r
+  if (alloc_size - filesize < 4)\r
+    alloc_size += 4; // padding for out-of-bound exec protection\r
 \r
   // Allocate space for the rom plus padding\r
-  rom=(unsigned char *)malloc(alloc_size);\r
-  if(rom) memset(rom+alloc_size-0x80000,0,0x80000);\r
+  rom = calloc(alloc_size, 1);\r
   return rom;\r
 }\r
 \r
 int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)\r
 {\r
-  unsigned char *rom=NULL; int size, bytes_read;\r
-  if (f==NULL) return 1;\r
+  unsigned char *rom;\r
+  int size, bytes_read;\r
+\r
+  if (f == NULL)\r
+    return 1;\r
 \r
-  size=f->size;\r
+  size = f->size;\r
   if (size <= 0) return 1;\r
-  size=(size+3)&~3; // Round up to a multiple of 4\r
+  size = (size+3)&~3; // Round up to a multiple of 4\r
 \r
   // Allocate space for the rom plus padding\r
-  rom=PicoCartAlloc(size);\r
-  if (rom==NULL) {\r
+  rom = PicoCartAlloc(size, is_sms);\r
+  if (rom == NULL) {\r
     elprintf(EL_STATUS, "out of memory (wanted %i)", size);\r
     return 2;\r
   }\r
@@ -491,15 +518,25 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)
     }\r
 \r
     // Check for SMD:\r
-    if (size >= 0x4200 && (size&0x3fff)==0x200 &&\r
+    if (size >= 0x4200 && (size&0x3fff) == 0x200 &&\r
         ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) {\r
+      elprintf(EL_STATUS, "SMD format detected.");\r
       DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD\r
     }\r
     else Byteswap(rom,size); // Just byteswap\r
   }\r
+  else\r
+  {\r
+    if (size >= 0x4200 && (size&0x3fff) == 0x200) {\r
+      elprintf(EL_STATUS, "SMD format detected.");\r
+      // at least here it's not interleaved\r
+      size -= 0x200;\r
+      memmove(rom, rom + 0x200, size);\r
+    }\r
+  }\r
 \r
-  if (prom)  *prom=rom;\r
-  if (psize) *psize=size;\r
+  if (prom)  *prom = rom;\r
+  if (psize) *psize = size;\r
 \r
   return 0;\r
 }\r
index debaa9b..d6b91bd 100644 (file)
@@ -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();
+}
+
index be819ee..d2ac82c 100644 (file)
@@ -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);
 
index 4acf22f..747f428 100644 (file)
@@ -40,7 +40,7 @@ unsigned char *HighCol=DefHighCol;
 #else\r
 unsigned char  HighCol[8+320+8];\r
 #endif\r
-unsigned short DefOutBuff[320*2];\r
+static unsigned int DefOutBuff[320*2/2];\r
 void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to\r
 \r
 static int  HighCacheA[41+1];   // caches for high layers\r
@@ -1269,7 +1269,7 @@ static void FinalizeLine8bit(int sh)
   int len, rs = rendstatus;\r
   static int dirty_count;\r
 \r
-  if (!sh && Pico.m.dirtyPal == 1 && DrawScanline < 222)\r
+  if (!sh && Pico.m.dirtyPal == 1)\r
   {\r
     // a hack for mid-frame palette changes\r
     if (!(rs & PDRAW_SONIC_MODE))\r
@@ -1306,22 +1306,6 @@ static void (*FinalizeLine)(int sh);
 \r
 // --------------------------------------------\r
 \r
-static void DrawBlankedLine(void)\r
-{\r
-  int sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight?\r
-\r
-  if (PicoScanBegin != NULL)\r
-    PicoScanBegin(DrawScanline);\r
-\r
-  BackFill(Pico.video.reg[7], sh);\r
-\r
-  if (FinalizeLine != NULL)\r
-    FinalizeLine(sh);\r
-\r
-  if (PicoScanEnd != NULL)\r
-    PicoScanEnd(DrawScanline);\r
-}\r
-\r
 static int DrawDisplay(int sh)\r
 {\r
   unsigned char *sprited = &HighLnSpr[DrawScanline][0];\r
@@ -1420,23 +1404,46 @@ PICO_INTERNAL void PicoFrameStart(void)
   rendstatus = 0;\r
   if ((Pico.video.reg[12]&6) == 6)\r
     rendstatus |= PDRAW_INTERLACE; // interlace mode\r
+  if (Pico.video.reg[1] & 8)\r
+    rendstatus |= PDRAW_240LINES;\r
 \r
-  if (Pico.m.dirtyPal) Pico.m.dirtyPal = 2; // reset dirty if needed\r
+  if (Pico.m.dirtyPal)\r
+    Pico.m.dirtyPal = 2; // reset dirty if needed\r
 \r
   DrawScanline=0;\r
   PrepareSprites(1);\r
   skip_next_line=0;\r
 }\r
 \r
-static void PicoLine(void)\r
+static void DrawBlankedLine(int line, int offs)\r
+{\r
+  int sh = (Pico.video.reg[0xC]&8)>>3; // shadow/hilight?\r
+\r
+  if (PicoScanBegin != NULL)\r
+    PicoScanBegin(line + offs);\r
+\r
+  BackFill(Pico.video.reg[7], sh);\r
+\r
+  if (FinalizeLine != NULL)\r
+    FinalizeLine(sh);\r
+\r
+  if (PicoScanEnd != NULL)\r
+    PicoScanEnd(line + offs);\r
+}\r
+\r
+static void PicoLine(int line, int offs)\r
 {\r
   int sh;\r
-  if (skip_next_line>0) { skip_next_line--; return; } // skip rendering lines\r
+  if (skip_next_line > 0) {\r
+    skip_next_line--;\r
+    return;\r
+  }\r
 \r
   sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight?\r
 \r
+  DrawScanline = line;\r
   if (PicoScanBegin != NULL)\r
-    skip_next_line = PicoScanBegin(DrawScanline);\r
+    skip_next_line = PicoScanBegin(line + offs);\r
 \r
   // Draw screen:\r
   BackFill(Pico.video.reg[7], sh);\r
@@ -1447,31 +1454,40 @@ static void PicoLine(void)
     FinalizeLine(sh);\r
 \r
   if (PicoScanEnd != NULL)\r
-    skip_next_line = PicoScanEnd(DrawScanline);\r
+    skip_next_line = PicoScanEnd(line + offs);\r
 }\r
 \r
 void PicoDrawSync(int to, int blank_last_line)\r
 {\r
-  for (; DrawScanline < to; DrawScanline++)\r
+  int line, offs = 0;\r
+\r
+  if (!(rendstatus & PDRAW_240LINES))\r
+    offs = 8;\r
+\r
+  for (line = DrawScanline; line < to; line++)\r
   {\r
 #if !CAN_HANDLE_240_LINES\r
-    if (DrawScanline >= 224) break;\r
+    if (line >= 224) break;\r
 #endif\r
-    PicoLine();\r
+    PicoLine(line, offs);\r
   }\r
 \r
 #if !CAN_HANDLE_240_LINES\r
-  if (DrawScanline >= 224) { DrawScanline = 240; return; }\r
+  if (line >= 224) {\r
+    DrawScanline = 240;\r
+    return;\r
+  }\r
 #endif\r
 \r
   // last line\r
-  if (DrawScanline <= to)\r
+  if (line <= to)\r
   {\r
     if (blank_last_line)\r
-         DrawBlankedLine();\r
-    else PicoLine();\r
-    DrawScanline++;\r
+         DrawBlankedLine(line, offs);\r
+    else PicoLine(line, offs);\r
+    line++;\r
   }\r
+  DrawScanline = line;\r
 }\r
 \r
 void PicoDrawSetColorFormat(int which)\r
@@ -1483,8 +1499,10 @@ void PicoDrawSetColorFormat(int which)
     case 0: FinalizeLine = FinalizeLineBGR444; break;\r
     default:FinalizeLine = NULL; break;\r
   }\r
+  PicoDrawSetColorFormatMode4(which);\r
 #if OVERRIDE_HIGHCOL\r
-  if (which) HighCol=DefHighCol;\r
+  if (which)\r
+    HighCol=DefHighCol;\r
 #endif\r
 }\r
 \r
index 7062a17..095250f 100644 (file)
@@ -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
 }
 
index 00184e6..c919507 100644 (file)
@@ -312,8 +312,12 @@ void PicoFrame(void)
 \r
 void PicoFrameDrawOnly(void)\r
 {\r
-  PicoFrameStart();\r
-  PicoDrawSync(223, 0);\r
+  if (!(PicoAHW & PAHW_SMS)) {\r
+    PicoFrameStart();\r
+    PicoDrawSync(223, 0);\r
+  } else {\r
+    PicoFrameDrawOnlyMS();\r
+  }\r
 }\r
 \r
 void PicoGetInternal(pint_t which, pint_ret_t *r)\r
index 68f6143..7436a60 100644 (file)
@@ -129,6 +129,7 @@ typedef struct
        void *param;            /* additional file related field */\r
        unsigned int size;      /* size */\r
        pm_type type;\r
+       char ext[4];\r
 } pm_file;\r
 pm_file *pm_open(const char *path);\r
 size_t   pm_read(void *ptr, size_t bytes, pm_file *stream);\r
@@ -170,6 +171,8 @@ extern int PicoDrawMask;
 #define PDRAW_SONIC_MODE    (1<<5) // mid-frame palette changes for 8bit renderer\r
 #define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3)\r
 #define PDRAW_SHHI_DONE     (1<<7) // layer sh/hi already processed\r
+#define PDRAW_240LINES      (1<<8) // 240 line display (224 if not set)\r
+#define PDRAW_192LINES      (1<<9) // 192 line display (for SMS games)\r
 extern int rendstatus;\r
 extern unsigned short HighPal[0x100];\r
 \r
@@ -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)\r
 extern void (*PicoPrepareCram)();    // prepares PicoCramHigh for renderer to use\r
 \r
-// mode4.c\r
-void PicoDrawSetColorFormatMode4(int which);\r
-\r
 // sound.c\r
 extern int PsndRate,PsndLen;\r
 extern short *PsndOut;\r
index 6aea7de..4a4418e 100644 (file)
@@ -427,6 +427,7 @@ PICO_INTERNAL void PicoFrameFull();
 void PicoFrameStartMode4(void);\r
 void PicoLineMode4(int line);\r
 void PicoDoHighPal555M4(void);\r
+void PicoDrawSetColorFormatMode4(int which);\r
 \r
 // memory.c\r
 PICO_INTERNAL void PicoInitPc(unsigned int pc);\r
@@ -567,6 +568,7 @@ void PicoPowerMS(void);
 void PicoResetMS(void);\r
 void PicoMemSetupMS(void);\r
 void PicoFrameMS(void);\r
+void PicoFrameDrawOnlyMS(void);\r
 \r
 // emulation event logging\r
 #ifndef EL_LOGMASK\r
index 25f53cb..ba9be50 100644 (file)
@@ -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);
+}
+
index 1cecc39..aca54be 100644 (file)
@@ -245,8 +245,11 @@ static int emu_cd_check(int *pregion, const char *fname_in)
 static int detect_media(const char *fname)\r
 {\r
        static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 };\r
+       static const char *sms_exts[] = { "sms", "gg", "sg" };\r
+       static const char *md_exts[] = { "gen", "bin", "smd" };\r
+       char buff0[32], buff[32];\r
+       unsigned short *d16;\r
        pm_file *pmf;\r
-       char buff[32];\r
        char ext[5];\r
        int i;\r
 \r
@@ -264,34 +267,69 @@ static int detect_media(const char *fname)
        if (pmf == NULL)\r
                return PM_BAD;\r
 \r
-       if (pm_read(buff, 32, pmf) != 32) {\r
+       if (pm_read(buff0, 32, pmf) != 32) {\r
                pm_close(pmf);\r
                return PM_BAD;\r
        }\r
 \r
-       if (strncasecmp("SEGADISCSYSTEM", buff + 0x00, 14) == 0 ||\r
-           strncasecmp("SEGADISCSYSTEM", buff + 0x10, 14) == 0) {\r
+       if (strncasecmp("SEGADISCSYSTEM", buff0 + 0x00, 14) == 0 ||\r
+           strncasecmp("SEGADISCSYSTEM", buff0 + 0x10, 14) == 0) {\r
                pm_close(pmf);\r
                return PM_CD;\r
        }\r
 \r
+       /* check for SMD evil */\r
+       if (pmf->size >= 0x4200 && (pmf->size & 0x3fff) == 0x200) {\r
+               if (pm_seek(pmf, sms_offsets[0] + 0x200, SEEK_SET) == sms_offsets[0] + 0x200 &&\r
+                   pm_read(buff, 16, pmf) == 16 &&\r
+                   strncmp("TMR SEGA", buff, 8) == 0)\r
+                       goto looks_like_sms;\r
+\r
+               /* could parse further but don't bother */\r
+               goto extension_check;\r
+       }\r
+\r
+       /* MD header? Act as TMSS BIOS here */\r
+       if (pm_seek(pmf, 0x100, SEEK_SET) == 0x100 && pm_read(buff, 16, pmf) == 16) {\r
+               if (strncmp(buff, "SEGA", 4) == 0 || strncmp(buff, " SEG", 4) == 0)\r
+                       goto looks_like_md;\r
+       }\r
+\r
        for (i = 0; i < array_size(sms_offsets); i++) {\r
                if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i])\r
-                       goto not_mark3;         /* actually it could be but can't be detected */\r
+                       continue;\r
 \r
                if (pm_read(buff, 16, pmf) != 16)\r
-                       goto not_mark3;\r
+                       continue;\r
 \r
-               if (strncasecmp("TMR SEGA", buff, 8) == 0) {\r
-                       pm_close(pmf);\r
-                       return PM_MARK3;\r
-               }\r
+               if (strncmp("TMR SEGA", buff, 8) == 0)\r
+                       goto looks_like_sms;\r
+       }\r
+\r
+extension_check:\r
+       /* probably some headerless thing. Maybe check the extension after all. */\r
+       for (i = 0; i < array_size(md_exts); i++)\r
+               if (strcasecmp(pmf->ext, md_exts[i]) == 0)\r
+                       goto looks_like_md;\r
+\r
+       for (i = 0; i < array_size(sms_exts); i++)\r
+               if (strcasecmp(pmf->ext, sms_exts[i]) == 0)\r
+                       goto looks_like_sms;\r
+\r
+       /* If everything else fails, make a guess on the reset vector */\r
+       d16 = (unsigned short *)(buff0 + 4);\r
+       if ((((d16[0] << 16) | d16[1]) & 0xffffff) >= pmf->size) {\r
+               lprintf("bad MD reset vector, assuming SMS\n");\r
+               goto looks_like_sms;\r
        }\r
 \r
-not_mark3:\r
+looks_like_md:\r
        pm_close(pmf);\r
-       /* the main emu function is to emulate MD, so assume MD */\r
        return PM_MD_CART;\r
+\r
+looks_like_sms:\r
+       pm_close(pmf);\r
+       return PM_MARK3;\r
 }\r
 \r
 static int extract_text(char *dest, const unsigned char *src, int len, int swab)\r
@@ -450,6 +488,7 @@ int emu_reload_rom(char *rom_fname)
 \r
        shutdown_MCD();\r
        PicoPatchUnload();\r
+       PicoAHW = 0;\r
 \r
        if (media_type == PM_CD)\r
        {\r
index dff1b39..08117df 100644 (file)
@@ -1803,7 +1803,7 @@ static void debug_menu_loop(void)
                {\r
                        case 0:\r
                                if (inp & PBTN_MOK)\r
-                                       SekStepM68k();\r
+                                       PDebugCPUStep();\r
                                if (inp & PBTN_MA3) {\r
                                        while (inp & PBTN_MA3)\r
                                                inp = in_menu_wait_any(-1);\r
diff --git a/platform/common/revision.mak b/platform/common/revision.mak
new file mode 100644 (file)
index 0000000..03093e3
--- /dev/null
@@ -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:
+
index fea424f..b8b1068 100644 (file)
@@ -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;
index ac79354..92e5d97 100644 (file)
@@ -65,7 +65,7 @@ ifeq "$(amalgamate)" "1"
 OBJS += ../../picoAll.o\r
 else\r
 OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o pico/z80if.o \\r
-               pico/videoport.o pico/draw2.o pico/draw.o pico/patch.o pico/debug.o\r
+               pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o pico/patch.o pico/debug.o\r
 # Pico - CD\r
 OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \\r
                pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \\r
@@ -120,12 +120,7 @@ DIRS = platform platform/gp2x platform/linux platform/common pico pico/cd pico/p
 all: mkdirs PicoDrive\r
 \r
 include ../common/common_arm.mak\r
-\r
-platform/common/menu.o : revision.h\r
-\r
-revision.h:\r
-       @echo "#define REVISION \"`svn info | grep Revision | cut -c 11-`\"" > /tmp/r.tmp\r
-       @diff -q $@ /tmp/r.tmp > /dev/null 2>&1 || mv -f /tmp/r.tmp $@\r
+include ../common/revision.mak\r
 \r
 # partial linking helps profiled builds due to section merging\r
 PicoDrive.o : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a\r
index 92e5b74..dd4b686 100644 (file)
@@ -220,7 +220,6 @@ static void draw_pico_ptr(void)
 \r
 static int EmuScanBegin16(unsigned int num)\r
 {\r
-       if (!(Pico.video.reg[1]&8)) num += 8;\r
        DrawLineDest = (unsigned short *) g_screen_ptr + g_screen_width * num;\r
 \r
        return 0;\r
@@ -228,7 +227,6 @@ static int EmuScanBegin16(unsigned int num)
 \r
 static int EmuScanBegin8(unsigned int num)\r
 {\r
-       if (!(Pico.video.reg[1]&8)) num += 8;\r
        DrawLineDest = (unsigned char *)  g_screen_ptr + g_screen_width * num;\r
 \r
        return 0;\r
@@ -247,8 +245,6 @@ static int EmuScanEnd16_rot(unsigned int num)
 {\r
        if ((num & 3) != 3)\r
                return 0;\r
-       if (!(Pico.video.reg[1] & 8))\r
-               num += 8;\r
        rotated_blit16(g_screen_ptr, rot_buff, num + 1,\r
                !(Pico.video.reg[12] & 1) && !(PicoOpt & POPT_EN_SOFTSCALE));\r
        return 0;\r
@@ -264,8 +260,6 @@ static int EmuScanEnd8_rot(unsigned int num)
 {\r
        if ((num & 3) != 3)\r
                return 0;\r
-       if (!(Pico.video.reg[1] & 8))\r
-               num += 8;\r
        rotated_blit8(g_screen_ptr, rot_buff, num + 1,\r
                !(Pico.video.reg[12] & 1));\r
        return 0;\r
@@ -439,7 +433,6 @@ static void vidResetMode(void)
        }\r
        else if (currentConfig.EmuOpt & EOPT_16BPP) {\r
                PicoDrawSetColorFormat(1);\r
-               PicoDrawSetColorFormatMode4(1);\r
                if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {\r
                        gp2x_video_changemode(-16);\r
                        PicoScanBegin = EmuScanBegin16_rot;\r
index be932ed..033d3bd 100644 (file)
@@ -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
index a9a2119..3fbda4a 100644 (file)
@@ -186,7 +186,6 @@ static void draw_pico_ptr(void)
 \r
 static int EmuScanBegin16(unsigned int num)\r
 {\r
-       if (!(Pico.video.reg[1]&8)) num += 8;\r
        DrawLineDest = (unsigned short *)g_screen_ptr + num*800 + 800/2 - 320/2;\r
        //int w = (Pico.video.reg[12]&1) ? 320 : 256;\r
        //DrawLineDest = (unsigned short *)g_screen_ptr + num*w;\r
@@ -204,7 +203,6 @@ static int EmuScanEnd16(unsigned int num)
        int sh = Pico.video.reg[0xC]&8;\r
        int len, mask = 0xff;\r
 \r
-       if (!(Pico.video.reg[1]&8)) num += 8;\r
        pd=(unsigned short *)g_screen_ptr + num*800*2 + 800/2 - 320*2/2;\r
 \r
        if (Pico.m.dirtyPal)\r
index e0e1ca1..5eca789 100644 (file)
@@ -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);
index b23a531..d004bdf 100644 (file)
@@ -92,7 +92,7 @@ static const unsigned long mask_numbers[] = {
 \r
 static int EmuScanBegin8(unsigned int num)\r
 {\r
-       DrawLineDest = PicoDraw2FB + 328*num + 328*8 + 8;\r
+       DrawLineDest = PicoDraw2FB + 328*num + 8;\r
 \r
        return 0;\r
 }\r
@@ -105,7 +105,7 @@ static int EmuScanEndFit0(unsigned int num)
        static int u = 0, num2 = 0;\r
        if(!num) u = num2 = 0;\r
 \r
-       DrawLineDest = PicoDraw2FB + 328*(++num2) + 328*8 + 8;\r
+       DrawLineDest = PicoDraw2FB + 328*(++num2) + 8;\r
 \r
        u += 6666;\r
 \r