“未经验证的一段数据作为代码运行会造成严重后果”,游戏卡带也是一样,因为接触不良或是数据储存芯片出错可能会导致严重的问题,简单的ROM校验可以算是解决这类问题的最简单的手段。任天堂在设计GB的时候也加入了ROM校验,GBSpec是这么描述的:
014D Complement check
(PROGRAM WON'T RUN ON GB IF NOT CORRECT!!!)
(It will run on Super GB, however, if incorrect.)
014E-014F Checksum (higher byte first) produced by
adding all bytes of a cartridge except for two
checksum bytes and taking two lower bytes of
the result. (GameBoy ignores this value.)
其中0X14D到0X14F就是校验的内容了,尤其是0X014D,要想在实际的硬件上运行是一定要正确的。那么具体这两个值是如何计算的呢?
代码如下:
u16 cartchecksum=0, calcchecksum=0; u8 cartcompchecksum=0, calccompchecksum=0; fflush( f ); fseek( f, 0, SEEK_SET ); for( i=0; i<(0x8000L<<calcromsize); i+=1 ) { ch=fgetc( f ); if( ch==EOF ) ch=0; if( i<0x0134L ) calcchecksum+=ch; else if( i<0x014DL ) { calccompchecksum+=ch; calcchecksum+=ch; } else if( i==0x014DL ) cartcompchecksum=ch; else if( i==0x014EL ) cartchecksum=ch<<8; else if( i==0x014FL ) cartchecksum|=ch; else calcchecksum+=ch; } calccompchecksum=0xE7-calccompchecksum; calcchecksum+=calccompchecksum;
其中calcromsize就是就是0x0148的值,代表的是32*2^n Bytes = 256*2^n bits = 2*2^n banks 的数据。
然后把calccompchecksum作为0x14D的值,calcchecksum的值作为0x14E-0x14F的值就没问题了。
参考:
1: GBSpec.txt by Martin Korth
2: RGBFIX by SurfSmurf and Otaku