Checksum Calculation Source
/*
This source code contains routines to manipulate
GameBoy ROM images. It is meant that source to be used
as a learning tool and not a tool of piracy.
*BorlandC 3.1 was used to compile this successfully.
It is a crime to redistribute these routines in a commercial
venture of any kind without permission or licensing agreement.
Contact us at our web page for more information on licensing.
(C)opyright 1995,96 Damaged Cybernetics
If you have any questions or comments, please contact the
following ppl via the Internet:
Donald Moore (MindRape) mindrape@goodnet.com
Donald Staheli (Royce) staheli@goodnet.com
Web Page: www.futureone.com/~damaged
Things that still need to be done is to calculate the compliment of
the GameBoy ROM image.
I'd like to thank DiskDude for his addtional help!
*/
#include
#include "gameboy.h"
// Magic string to check for
unsigned char DETECT_GAMEBOY_MAJIC[] =
{ 0xCE,0xED,0x66,0x66,0xCC,0x0D,0x00,0x0B,0x03,0x73,0x00,0x83,
0x00,0x0C,0x00,0x0D,0x00,0x08,0x11,0x1F,0x88,0x89,0x00,0x0E,
0xDC,0xCC,0x6E,0xE6,0xDD,0xDD,0xD9,0x99,0xBB,0xBB,0x67,0x63,
0x6E,0x0E,0xEC,0xCC,0xDD,0xDC,0x99,0x9F,0xBB,0xB9,0x33,0x3E
};
/*
unsigned int swapint(unsigned int uiValue)
ENT: unsigned int uiValue - Value to swap bytes
RET: unsigned int
Swap a 16 bit integer value bytes around.
*/
unsigned int swapint(unsigned int uiValue)
{return(uiValue = (uiValue << 8) | (uiValue >> 8));}
/*
void PutGBCheckSum(FILE *source,unsigned uiCheckSum)
ENT: FILE *source - Stream handle to get the GameBoy checksum
unsigned int uiCheckSum - checksum value to write out to Gameboy
image
RET:
Put the GameBoy checksum value into the rom image. Please make sure
your in write mode, or update mode. Lots of people make this mistake.
This routine preserves the original offset in the stream.
*/
void PutGBCheckSum(FILE *source,unsigned int uiCheckSum)
{ unsigned long ulOldOffset = 0L;
// save the old offset in the file
ulOldOffset = ftell(source);
// jump to CheckSum Location
fseek(source,(long) GB_CHECKSUM_OFFSET1,SEEK_SET);
/*
We need to swap the 2 bytes around on Little Edian machines since
the GameBoy is Big Edian.
*/
uiCheckSum = swapint(uiCheckSum);
// the checksum is 2 bytes
fwrite(&uiCheckSum,1,2,source);
// jump back to the old offset in the file
fseek(source,ulOldOffset,SEEK_SET);
}
/*
unsigned int GetGBCheckSum(FILE *source,unsigned int uiOffset)
ENT: FILE *source - Stream handle to get the GameBoy checksum
unsigned int uiOffset - correct offset to grab checksum
RET: GameBoy Rom checksum from the file.
Grab the GameBoy checksum value form the rom image.
This routine preserves the original offset in the stream.
*/
unsigned int GetGBCheckSum(FILE *source,unsigned int uiOffset)
{ unsigned long ulOldOffset = 0L;
unsigned int uiCheckSum = 0;
// save the old offset in the file
ulOldOffset = ftell(source);
// Jump to CheckSum Location
fseek(source,(long) GB_CHECKSUM_OFFSET1+uiOffset,SEEK_SET);
// the checksum is 2 bytes
fread(&uiCheckSum,2,1,source);
/* We need to swap the 2 bytes around on Little Edian
machines since the GameBoy is Big Edian. */
uiCheckSum = swapint(uiCheckSum);
// jump back to the old offset in the file
fseek(source,ulOldOffset,SEEK_SET);
// return the Checksum we found
return(uiCheckSum);
}
/*
unsigned char Check4GameBoy
(unsigned char *szStr2check,unsigned int uiOffset)
ENT: unsigned char *szStr2check - Buffer holding area to search
unsigned int uiOffset - Starting position to start
looking in string
RET:TRUE - valid GameBoy image
FALSE - invalid GameBoy image
Compare szStr2check with DETECT_GAMEBOY_MAJIC. If szStr2check
matches the majic value then we have a real gameboy image.
*/
unsigned char Check4GameBoy
(unsigned char *szStr2check,unsigned int uiOffset)
{int i;
for (i=0;i < DETECT_GAMEBOY_MAJIC_SIZE;i++)
if (szStr2check[i+uiOffset] != DETECT_GAMEBOY_MAJIC[i])
return(FALSE);
return(TRUE);
}
/*
char DetectGameBoy(FILE *source)
ENT: FILE *source - Stream handle to get the GameBoy checksum
RET: DETECT_GAMEBOY_HEADER - Found a GameBoy image w/header
DETECT_GAMEBOY_RAW - Found a Gameboy image w/o header
DETECT_GAMEBOY_INVALID - Invalid GameBoy image
Try to detect if we have a valid gameboy image.
This routine preserves the original offset in the stream.
*/
char DetectGameBoy(FILE *source)
{ unsigned char ucBuffer[DETECT_GAMEBOY_BUFFER_SIZE];
// hold our old offset in the stream
unsigned long ulOldOffset = 0L;
// hold our majic signature value
unsigned ucMajic;
// hold our return value
unsigned int uiRetVal;
// save the old offset in the file
ulOldOffset = ftell(source);
// rewind back file position 0
rewind(source);
fseek(source,0L,SEEK_SET);
fread(ucBuffer,1,DETECT_GAMEBOY_BUFFER_SIZE,source);
/* Ok since the FIG header format is impossible to detect dued to
lack of information about the format and the intial information
didn't really look possible. Also many GB copiers don't do the
header correctly anyways =(. Next solution check for the
Majic signature that MUST exist in all GB games, the Nintendo
character area.
What we do is look for it in it's normal place, if that fails
look in the same place offseted by 512 bytes.
*/
// Check for without header
if (Check4GameBoy(ucBuffer,DETECT_GAMEBOY_MAJIC_RAW_POS))
uiRetVal = DETECT_GAMEBOY_RAW;
else
{
// check for with header
if (Check4GameBoy(ucBuffer,DETECT_GAMEBOY_MAJIC_HEADR_POS))
uiRetVal = DETECT_GAMEBOY_HEADER;
// not a valid GB image!
else
uiRetVal = DETECT_GAMEBOY_INVALID;
}
// ok back to the old file position
fseek(source,ulOldOffset,SEEK_SET);
return(uiRetVal);
}
/*
unsigned int CalculateGBCheckSum(FILE *source,unsigned int uiOffset)
ENT: FILE *source - Stream handle of file to calculate GameBoy checksum
unsigned int uiOffset - The offset to start calculating at
RET: GB Checksum
Calculate the Gameboy ROM Image checksum value.
unsigned int CalculateGBCheckSum(FILE *source,unsigned int uiOffset)
{
// hold our old offset in the stream
unsigned long ulOldOffset = 0L;
// store our calculated checksum here
unsigned int uiCheckSum = 0;
unsigned char ucBuffer[BUFFER_SIZE];
unsigned int i;
// keep track of our buffer size
unsigned int uiSize;
// keep track of our position in the file
unsigned long ulTotalFileSize = 0L;
// save the old offset in the file
ulOldOffset = ftell(source);
// seek to the correct offset to start
fseek(source,uiOffset,SEEK_SET);
/*
The gameboy calculates it's checksum by adding each byte up in the
ROM image, except for it's checksum bytes. The checksum bytes are
located at offsets GB_CHECKSUM_OFFSET1 and GB_CHECKSUM_OFFSET2.
The checksum is a 32bit value. Calculate it by adding every byte
up in the ROM (don't include the copier header if there is one).
Once we are finished we take the lower 16bits and return it.
In this following piece of code we use a 16bit integer and let it
overflow (quite a few times :>) so we don't have to do an xor 0xFFFF
later on.
*/
while (!feof(source))
{
uiSize = fread(ucBuffer,1,BUFFER_SIZE,source);
for (i=0;i < uiSize;i++)
{
if (ulTotalFileSize != GB_CHECKSUM_OFFSET1
&& ulTotalFileSize != GB_CHECKSUM_OFFSET2)
uiCheckSum += ucBuffer[i];
// keep track of our position in the file we could use ftell()
// but its too slow
ulTotalFileSize++;
}
}
// ok back to the old file position
fseek(source,ulOldOffset,SEEK_SET);
// return our checksum
return(uiCheckSum);
}
Damaged Cybernetics is not connected or affiliated with any mentioned
company in any way. The opinions of Damaged Cybernetics do not reflect the
views of the various companies mentioned here. Companies and all products
pertaining to that company are trademarks of that company. Please contact
that company for trademark and copyright information.
© 1996 Damaged Cybernetics All Rights Reserved
|