png screenshot support
[drnoksnes] / sdd1.cpp
index 3baae1b..439df53 100644 (file)
--- a/sdd1.cpp
+++ b/sdd1.cpp
  * Super NES and Super Nintendo Entertainment System are trademarks of
  * Nintendo Co., Limited and its subsidiary companies.
  */
+
+#include <stdio.h>
+#include <dirent.h>
+
 #include "snes9x.h"
 #include "memmap.h"
 #include "ppu.h"
 #include "sdd1.h"
-#include "display.h"
 
-#ifdef __linux
-//#include <unistd.h>
+static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2)
+{
+    return (*(uint32 *) p1 - *(uint32 *) p2);
+}
+
+static int S9xGetSDD1Dir(char * packdir)
+{
+       char dir[_MAX_DIR + 1];
+       char drive[_MAX_DRIVE + 1];
+       char name[_MAX_FNAME + 1];
+       char ext[_MAX_EXT + 1];
+
+       PathSplit(S9xGetFilename(FILE_ROM), drive, dir, name, ext);
+
+       if (strncmp(Memory.ROMName, "Star Ocean", 10) == 0) {
+        PathMake(packdir, drive, dir, "socnsdd1", 0);
+        return 1;
+       } else if(strncmp(Memory.ROMName, "STREET FIGHTER ALPHA2", 21) == 0) {
+               PathMake(packdir, drive, dir, "sfa2sdd1", 0);
+               return 1;
+       } else {
+               S9xMessage(S9X_WARNING, S9X_ROM_INFO,
+                       "WARNING: No default SDD1 pack for this ROM");
+               return 0;
+       }
+}
+
+void S9xLoadSDD1Data ()
+{
+       char packdir[_MAX_PATH + 1];
+
+       // Unload any previous pack
+       Settings.SDD1Pack = FALSE;
+       Memory.FreeSDD1Data();
+
+       if (!S9xGetSDD1Dir(packdir)) {
+               printf("SDD1: Didn't found pack for this ROM\n");
+               return;
+       }
+
+       printf("SDD1: Searching for pack in %s\n", packdir);
+       Settings.SDD1Pack=TRUE;
+
+       char index[_MAX_PATH + 1];
+       char data[_MAX_PATH + 1];
+       char patch[_MAX_PATH + 1];
+       DIR *dir = opendir(packdir);
+
+       index[0] = 0;
+       data[0] = 0;
+       patch[0] = 0;
+
+       if (dir) {
+               struct dirent *d;
+
+               while ((d = readdir (dir))) {
+                       if (strcasecmp (d->d_name, "SDD1GFX.IDX") == 0) {
+                               strcpy(index, packdir);
+                               strcat(index, "/");
+                               strcat(index, d->d_name);
+                       } else if (strcasecmp (d->d_name, "SDD1GFX.DAT") == 0) {
+                               strcpy(data, packdir);
+                               strcat(data, "/");
+                               strcat(data, d->d_name);
+                       } else if (strcasecmp (d->d_name, "SDD1GFX.PAT") == 0) {
+                               strcpy(patch, packdir);
+                               strcat(patch, "/");
+                               strcat(patch, d->d_name);
+                       }
+               }
+               closedir (dir);
+       }
+
+       if (strlen (index) && strlen (data)) {
+               FILE *fs = fopen (index, "rb");
+               size_t len = 0;
+
+               if (fs) {
+                       // Index is stored as a sequence of entries, each entry being
+                       // 12 bytes consisting of:
+                       // 4 byte key: (24bit address & 0xfffff * 16) | translated block
+                       // 4 byte ROM offset
+                       // 4 byte length
+
+                       fseek (fs, 0, SEEK_END);
+                       len = ftell (fs);
+                       rewind (fs);
+                       Memory.SDD1Index = (uint8 *) malloc (len);
+                       if (fread (Memory.SDD1Index, 1, len, fs) < len) {
+                               fprintf(stderr, "Failed to fully read SDD1 index file %s\n",
+                                       data);
+                       }
+                       fclose (fs);
+                       Memory.SDD1Entries = len / 12;
+               } else {
+                       fprintf(stderr, "Failed to read SDD1 index file %s\n", index);
+                       return;
+               }
+               printf("SDD1: index: %s\n", PathBasename(index));
+
+               if (!(fs = fopen (data, "rb"))) {
+                       fprintf(stderr, "Failed to read SDD1 data file %s\n", data);
+                       free ((char *) Memory.SDD1Index);
+                       Memory.SDD1Index = NULL;
+                       Memory.SDD1Entries = 0;
+                       return;
+               } else {
+                       fseek (fs, 0, SEEK_END);
+                       len = ftell (fs);
+                       rewind (fs);
+                       Memory.SDD1Data = (uint8 *) malloc (len);
+                       if (fread (Memory.SDD1Data, 1, len, fs) < len) {
+                               fprintf(stderr, "Failed to fully read SDD1 data file %s\n",
+                                       data);
+                       }
+                       fclose (fs);
+               }
+               printf("SDD1: data pack: %s\n", PathBasename(data));
+
+               if (strlen (patch) > 0 && (fs = fopen (patch, "rb"))) {
+                       fclose (fs);
+               }
+
+#ifdef MSB_FIRST
+               // Swap the byte order of the 32-bit value triplets on
+               // MSBFirst machines.
+               uint8 *ptr = Memory.SDD1Index;
+               for (int i = 0; i < Memory.SDD1Entries; i++, ptr += 12)         {
+                       SWAP_DWORD ((*(uint32 *) (ptr + 0)));
+                       SWAP_DWORD ((*(uint32 *) (ptr + 4)));
+                       SWAP_DWORD ((*(uint32 *) (ptr + 8)));
+               }
 #endif
 
+               qsort(Memory.SDD1Index, Memory.SDD1Entries, 12,
+                       S9xCompareSDD1IndexEntries);
+               printf("SDD1: Pack loaded succesfully\n");
+       } else {
+               fprintf(stderr, "SDD1: SDD1 data pack not found in '%s'\n",
+                       packdir);
+               fprintf(stderr, "SDD1: Check if sdd1gfx files exist\n");
+               printf("SDD1: Failed to load pack\n");
+       }
+}
+
 void S9xSetSDD1MemoryMap (uint32 bank, uint32 value)
 {
     bank = 0xc00 + bank * 0x100;
@@ -102,16 +246,17 @@ void S9xSDD1SaveLoggedData ()
        qsort (Memory.SDD1LoggedData, Memory.SDD1LoggedDataCount, 8,
               S9xCompareSDD1LoggedDataEntries);
 
-       FILE *fs = fopen (S9xGetFilename (".dat"), "wb");
+       const char * sdd1_dat_file = S9xGetFilename(FILE_SDD1_DAT);
+       FILE *fs = fopen(sdd1_dat_file, "wb");
 
        if (fs)
        {
-           fwrite (Memory.SDD1LoggedData, 8,
-                   Memory.SDD1LoggedDataCount, fs);
-           fclose (fs);
-#if defined(__linux)
-           chown (S9xGetFilename (".dat"), getuid (), getgid ());
-#endif
+           size_t c = fwrite(Memory.SDD1LoggedData, 8,
+                               Memory.SDD1LoggedDataCount, fs);
+               if (c < Memory.SDD1LoggedDataCount) {
+                       fprintf(stderr, "Failed to write sdd1 log data\n");
+               }
+           fclose(fs);
        }
        Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount;
     }
@@ -119,16 +264,16 @@ void S9xSDD1SaveLoggedData ()
 
 void S9xSDD1LoadLoggedData ()
 {
-    FILE *fs = fopen (S9xGetFilename (".dat"), "rb");
+    FILE *fs = fopen (S9xGetFilename(FILE_SDD1_DAT), "rb");
 
     Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0;
 
     if (fs)
     {
-       int c = fread (Memory.SDD1LoggedData, 8, 
-                      MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs);
+       size_t c = fread (Memory.SDD1LoggedData, 8,
+                           MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs);
 
-       if (c != EOF)
+       if (c > 0)
            Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c;
        fclose (fs);
     }