close

SEGA-RETRO.JPG


最近在研究 SEGA-Genesis 卡匣 (Cartridge) ROM 格式, 以經成功 Decode SEGA-Genesis 卡匣 ROM 格式, 因此將心得 Post 在 Blog 上, 提供參考. 

 

 


H100: Console Name
 

控制台名稱, 它可以是 "SEGA MEGA DRIVE" 或 "SEGA GENESIS" 取決於控制台的原產國. 
 

Sega-ConsoleName.png
 

 

H1A0: ROM 容量
 

ROM容量.  在這裡你會找到 ROM 的開始和結束地址 (00000000, XXXXXXXX) . 在大多數情況下, 起始地址為0, 結束地址為 以 BYTE 為單位的 ROM 的大小. 在此範例中ROM Size = (0X002FFFFF + 1) , 也就是 3MB. 為何要加 1? 因開始地址由 0 算起. 
 

Sega-RomSize.png
 

請看檔案最後, 上述結束地址剛好是這個檔案的最後. 
 

Sega-RomLast.png


 

範例程式
 

在這個範例程式中, 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

 

 

 

 

 

 

 

 

arrow
arrow
    文章標籤
    SEGA GENESIS ROM ROM format
    全站熱搜
    創作者介紹
    創作者 Lexra 的頭像
    Lexra

    Lexra Pixnet

    Lexra 發表在 痞客邦 留言(0) 人氣()