close
最近在研究 SEGA-Genesis 卡匣 (Cartridge) ROM 格式, 以經成功 Decode SEGA-Genesis 卡匣 ROM 格式, 因此將心得 Post 在 Blog 上, 提供參考.
H100: Console Name
控制台名稱, 它可以是 "SEGA MEGA DRIVE" 或 "SEGA GENESIS" 取決於控制台的原產國.
H1A0: ROM 容量
ROM容量. 在這裡你會找到 ROM 的開始和結束地址 (00000000, XXXXXXXX) . 在大多數情況下, 起始地址為0, 結束地址為 以 BYTE 為單位的 ROM 的大小. 在此範例中ROM Size = (0X002FFFFF + 1) , 也就是 3MB. 為何要加 1? 因開始地址由 0 算起.
請看檔案最後, 上述結束地址剛好是這個檔案的最後.
範例程式
在這個範例程式中, Dump 出 ROM File. 根據上述的 Console Name 來判斷 SEGA-Genesis Cartridge 是否已經插上. 根據上述提及的 Rom Capacity 來決定需要 Dump 的大小.
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdarg.h> #include <stdlib.h> #include <time.h> #include <sys/mount.h> // for mount #include <fcntl.h> #include <signal.h> #include <netinet/tcp.h> #include <inttypes.h> #include <sched.h> #include <assert.h> #include <sys/ioctl.h> /////////////////////////////////////////////////////////// // #define BUILD_UINT16(loByte, hiByte) \ ((unsigned short)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \ ((unsigned int)((unsigned int)((Byte0) & 0x00FF) + ((unsigned int)((Byte1) & 0x00FF) << 8) \ + ((unsigned int)((Byte2) & 0x00FF) << 16) + ((unsigned int)((Byte3) & 0x00FF) << 24))) #define HI_UINT16(a) (((a) >> 8) & 0xFF) #define LO_UINT16(a) ((a) & 0xFF) /////////////////////////////////////////////////////////// // #define CARDS_IOC_MAGIC 'k' #define CARDS_IOCGETSECTOR _IOWR(CARDS_IOC_MAGIC, 2, int) #define CARDS_IOCSETOFFSET _IOWR(CARDS_IOC_MAGIC, 6, int) #define CARDS_IOCSTART_WIRELESSKEY_SCAN _IOWR(CARDS_IOC_MAGIC, 7, int) #define CARDS_IOCSTOP_WIRELESSKEY_SCAN _IOWR(CARDS_IOC_MAGIC, 8, int) #define CARDS_IOCSWITCHKEY _IOWR(CARDS_IOC_MAGIC, 4, int) #define CARDS_IOCSWITCHCARD _IOWR(CARDS_IOC_MAGIC, 5, int) /////////////////////////////////////////////////////////// // #define CARDS_MAX_512B_SECTORS 16384 /////////////////////////////////////////////////////////// // int main (int argc, char **argv) { unsigned char data[1024] = { 0 }; int res; int fd = -1; int cardaddress = 0; int i; int j; FILE *f = 0; int offset = 0; int length = -1; fd = open("/dev/cards", O_RDWR); if (-1 == fd) printf("OPEN() FAIL\n"), exit(1); res = ioctl(fd, CARDS_IOCSWITCHCARD, 0); if (0 != res) printf("CARDS_IOCSWITCHCARD FAIL\n"), exit(1); printf("CARDS_IOCSWITCHCARD\n"); res = ioctl(fd, CARDS_IOCSETOFFSET, (unsigned long)&cardaddress); if (0 != res) printf("CARDS_IOCSETOFFSET FAIL\n"), exit(1); printf("CARDS_IOCSETOFFSET\n"); f = fopen("/mnt/asec/cartridge.bin", "wb"), assert(0 != f); if (0 == f) printf("FOPEN() FAIL\n"), close(fd), exit(1); system("chmod 666 /mnt/asec/cartridge.bin"); for (i = 0; i < CARDS_MAX_512B_SECTORS; i++) { if (offset >= length && -1 != length) break; memset(data, 0, sizeof(data)); res = ioctl(fd, CARDS_IOCGETSECTOR, (unsigned long)data); if (0 != res) printf("CARDS_IOCGETSECTOR FAIL\n"), fclose(f), close(fd), exit(1); // 53 45 47 41 20 "SEGA " if (0 == i) { if (0x53 == data[0x100] && 0x45 == data[0x101] && 0x47 == data[0x102] && 0x41 == data[0x103]) { int remainder; length = (int)BUILD_UINT32(data[0x1a7], data[0x1a6], data[0x1a5], data[0x1a4]); remainder = length % 512; if (0 != remainder) length += (512 - remainder); printf("SEGA=%d\n", length); } else { int l = 0; printf("NO SEGA\n"), fclose(f), close(fd); for (j = 0; j < 512; j++) { if (15 == (j % 16)) printf("%02X\n", data[j]); else if (0 == (j % 16)) { printf("%08X\t%02X ", l, data[j]); l += 16; } else printf("%02X ", data[j]); } printf("\n"); exit(1); } } else { printf("."); } fwrite(data, 512, 1, f); cardaddress += 256; offset += 512; } fclose(f); printf("\n"); close(fd); return 0; }
Reference
https://www.zophar.net/fileuploads/2/10614uauyw/Genesis_ROM_Format.txt
文章標籤
全站熱搜
留言列表