最近在研究 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
文章標籤
全站熱搜
