mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Rewrite rgbfix from scratch, under a free ISC license.
Slight changes in usage; the man page has been updated accordingly.
This commit is contained in:
37
man/rgbfix.1
37
man/rgbfix.1
@@ -7,9 +7,11 @@
|
|||||||
.\" SECTION
|
.\" SECTION
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm rgbfix
|
.Nm rgbfix
|
||||||
.Op Fl Ccdjqrsv
|
.Op Fl Ccjsv
|
||||||
.Op Fl k Ar licensee_str
|
.Op Fl k Ar licensee_str
|
||||||
|
.Op Fl l Ar licensee_id
|
||||||
.Op Fl m Ar mbc_type
|
.Op Fl m Ar mbc_type
|
||||||
|
.Op Fl n Ar rom_version
|
||||||
.Op Fl p Ar pad_value
|
.Op Fl p Ar pad_value
|
||||||
.Op Fl r Ar ram_size
|
.Op Fl r Ar ram_size
|
||||||
.Op Fl t Ar title_str
|
.Op Fl t Ar title_str
|
||||||
@@ -24,19 +26,18 @@ The arguments are as follows:
|
|||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl C
|
.It Fl C
|
||||||
Set the Game Boy Color compatible flag: [0x143] = 0x80.
|
Set the Game Boy Color\(enonly flag: [0x143] = 0xC0.
|
||||||
This flag and the
|
If both this and the
|
||||||
.Fl c
|
.Fl c
|
||||||
flag are mutually exclusive.
|
flag are set, this takes precedence.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl c
|
.It Fl c
|
||||||
Set the Game Boy Color only flag: [0x143] = 0xC0.
|
Set the Game Boy Color\(encompatible flag: [0x143] = 0x80.
|
||||||
This flag and the
|
If both this and the
|
||||||
.Fl C
|
.Fl C
|
||||||
flag are mutually exclusive.
|
flag are set,
|
||||||
.\" ITEM
|
.Fl C
|
||||||
.It Fl d
|
takes precedence.
|
||||||
Don't perform any changes, just pretend to for debugging.
|
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl j
|
.It Fl j
|
||||||
Set the non-Japanese region flag: [0x14A] = 1.
|
Set the non-Japanese region flag: [0x14A] = 1.
|
||||||
@@ -45,9 +46,16 @@ Set the non-Japanese region flag: [0x14A] = 1.
|
|||||||
Set the new licensee string ([0x144\(en0x145]) to a given string, truncated
|
Set the new licensee string ([0x144\(en0x145]) to a given string, truncated
|
||||||
to at most two characters.
|
to at most two characters.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
|
.It Fl l Ar licensee_id
|
||||||
|
Set the old licensee code, [0x14B], to a given value from 0 to 0xFF.
|
||||||
|
This value is deprecated and should be set to 0x33 in all new software.
|
||||||
|
.\" ITEM
|
||||||
.It Fl m Ar mbc_type
|
.It Fl m Ar mbc_type
|
||||||
Set the MBC type, [0x147], to a given value from 0 to 0xFF.
|
Set the MBC type, [0x147], to a given value from 0 to 0xFF.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
|
.It Fl n Ar rom_version
|
||||||
|
Set the ROM version, [0x14C], to a given value from 0 to 0xFF.
|
||||||
|
.\" ITEM
|
||||||
.It Fl p Ar pad_value
|
.It Fl p Ar pad_value
|
||||||
Pad the image to a valid size with a given pad value from 0 to 0xFF.
|
Pad the image to a valid size with a given pad value from 0 to 0xFF.
|
||||||
.Nm
|
.Nm
|
||||||
@@ -55,14 +63,11 @@ will automatically pick a size from 32KiB, 64KiB, 128KiB, ..., 8192KiB and
|
|||||||
give a warning thereafter.
|
give a warning thereafter.
|
||||||
The cartridge size byte ([0x148]) will be changed to reflect this new size.
|
The cartridge size byte ([0x148]) will be changed to reflect this new size.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl q
|
|
||||||
Enable quiet mode, suppressing all text except errors.
|
|
||||||
.\" ITEM
|
|
||||||
.It Fl r Ar ram_size
|
.It Fl r Ar ram_size
|
||||||
Set the RAM size, [0x149], to a given value from 0 to 0xFF.
|
Set the RAM size, [0x149], to a given value from 0 to 0xFF.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl s
|
.It Fl s
|
||||||
Set the SGB flag: [0x146] = 3, and set the old licensee code: [0x14B] = 0x33.
|
Set the SGB flag: [0x146] = 3.
|
||||||
.\" ITEM
|
.\" ITEM
|
||||||
.It Fl t Ar title
|
.It Fl t Ar title
|
||||||
Set the title string ([0x134\(en0x143]) to a given string, truncated to at
|
Set the title string ([0x134\(en0x143]) to a given string, truncated to at
|
||||||
@@ -97,12 +102,12 @@ The following will make a SGB-enabled, color-enabled game with a title of
|
|||||||
(The Game Boy itself does not use the title, but some emulators or ROM managers
|
(The Game Boy itself does not use the title, but some emulators or ROM managers
|
||||||
might.)
|
might.)
|
||||||
.Pp
|
.Pp
|
||||||
.D1 $ rgbfix \-vCs \-p 0 \-t foobar baz.gb
|
.D1 $ rgbfix \-vcs \-p 0 \-t foobar baz.gb
|
||||||
.Pp
|
.Pp
|
||||||
The following will duplicate the header (sans global checksum) of the game
|
The following will duplicate the header (sans global checksum) of the game
|
||||||
"Survival Kids":
|
"Survival Kids":
|
||||||
.Pp
|
.Pp
|
||||||
.D1 $ rgbfix \-Cjsv \-k A4 \-m 0x1B \-p 0xFF \-r 3 \-t SURVIVALKIDAVKE SurvivalKids.gbc
|
.D1 $ rgbfix \-cjsv \-k A4 \-m 0x1B \-p 0xFF \-r 3 \-t SURVIVALKIDAVKE SurvivalKids.gbc
|
||||||
.\" SECTION
|
.\" SECTION
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rgbds 7 ,
|
.Xr rgbds 7 ,
|
||||||
|
|||||||
386
src/fix/main.c
386
src/fix/main.c
@@ -15,19 +15,403 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
printf("usage: rgbfix [-Ccjsv] [-k licensee_str] [-l licensee_id] "
|
||||||
|
"[-m mbc_type]\n" " [-n rom_version] [-p pad_value] "
|
||||||
|
"[-r ram_size] [-t title_str] file.gb\n");
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *rom;
|
FILE *rom;
|
||||||
|
int ch;
|
||||||
|
char *ep;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the ROM file
|
||||||
|
*/
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
errx(1, "Usage: rgbfix romfile");
|
usage();
|
||||||
|
|
||||||
if ((rom = fopen(argv[argc - 1], "rb+")) == NULL)
|
if ((rom = fopen(argv[argc - 1], "rb+")) == NULL)
|
||||||
err(1, "Error opening file %s", argv[argc - 1]);
|
err(1, "Error opening file %s", argv[argc - 1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse command-line options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* all flags default to false unless options specify otherwise */
|
||||||
|
bool validate = false;
|
||||||
|
bool settitle = false;
|
||||||
|
bool colorcompatible = false;
|
||||||
|
bool coloronly = false;
|
||||||
|
bool nonjapan = false;
|
||||||
|
bool setlicensee = false;
|
||||||
|
bool setnewlicensee = false;
|
||||||
|
bool super = false;
|
||||||
|
bool setcartridge = false;
|
||||||
|
bool setramsize = false;
|
||||||
|
bool resize = false;
|
||||||
|
bool setversion = false;
|
||||||
|
|
||||||
|
char *title = NULL; /* game title in ASCII */
|
||||||
|
char *newlicensee = NULL; /* new licensee ID, two ASCII characters */
|
||||||
|
|
||||||
|
int licensee = -1; /* old licensee ID */
|
||||||
|
int cartridge = -1; /* cartridge hardware ID */
|
||||||
|
int ramsize = -1; /* RAM size ID */
|
||||||
|
int version = -1; /* mask ROM version number */
|
||||||
|
int padvalue = -1; /* to pad the rom with if it changes size */
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "Ccjk:l:m:n:p:sr:t:v")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'C':
|
||||||
|
coloronly = true;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 'c':
|
||||||
|
colorcompatible = true;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
nonjapan = true;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
setnewlicensee = true;
|
||||||
|
|
||||||
|
if (strlen(optarg) != 2)
|
||||||
|
errx(1, "New licensee code %s is not the "
|
||||||
|
"correct length of 2 characters", optarg);
|
||||||
|
|
||||||
|
newlicensee = optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
setlicensee = true;
|
||||||
|
|
||||||
|
licensee = strtoul(optarg, &ep, 0);
|
||||||
|
if (optarg[0] == '\0' || *ep != '\0')
|
||||||
|
errx(1, "Invalid argument for option 'l'");
|
||||||
|
if (licensee < 0 || licensee > 0xFF)
|
||||||
|
errx(1, "Argument for option 'l' must be "
|
||||||
|
"between 0 and 255");
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
setcartridge = true;
|
||||||
|
|
||||||
|
cartridge = strtoul(optarg, &ep, 0);
|
||||||
|
if (optarg[0] == '\0' || *ep != '\0')
|
||||||
|
errx(1, "Invalid argument for option 'm'");
|
||||||
|
if (cartridge < 0 || cartridge > 0xFF)
|
||||||
|
errx(1, "Argument for option 'm' must be "
|
||||||
|
"between 0 and 255");
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
setversion = true;
|
||||||
|
|
||||||
|
version = strtoul(optarg, &ep, 0);
|
||||||
|
if (optarg[0] == '\0' || *ep != '\0')
|
||||||
|
errx(1, "Invalid argument for option 'n'");
|
||||||
|
if (version < 0 || version > 0xFF)
|
||||||
|
errx(1, "Argument for option 'n' must be "
|
||||||
|
"between 0 and 255");
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
resize = true;
|
||||||
|
|
||||||
|
padvalue = strtoul(optarg, &ep, 0);
|
||||||
|
if (optarg[0] == '\0' || *ep != '\0')
|
||||||
|
errx(1, "Invalid argument for option 'p'");
|
||||||
|
if (padvalue < 0 || padvalue > 0xFF)
|
||||||
|
errx(1, "Argument for option 'p' must be "
|
||||||
|
"between 0 and 255");
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
setramsize = true;
|
||||||
|
|
||||||
|
ramsize = strtoul(optarg, &ep, 0);
|
||||||
|
if (optarg[0] == '\0' || *ep != '\0')
|
||||||
|
errx(1, "Invalid argument for option 'r'");
|
||||||
|
if (ramsize < 0 || ramsize > 0xFF)
|
||||||
|
errx(1, "Argument for option 'r' must be "
|
||||||
|
"between 0 and 255");
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
super = true;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
settitle = true;
|
||||||
|
|
||||||
|
if (strlen(optarg) > 16)
|
||||||
|
errx(1, "Title %s is greater than the "
|
||||||
|
"maximum of 16 characters", optarg);
|
||||||
|
|
||||||
|
if (strlen(optarg) == 16)
|
||||||
|
warnx("Title %s is 16 chars, it is best "
|
||||||
|
"to keep it to 15 or fewer", optarg);
|
||||||
|
|
||||||
|
title = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
validate = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write changes to ROM
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (validate) {
|
||||||
|
/*
|
||||||
|
* Offset 0x104–0x133: Nintendo Logo
|
||||||
|
* This is a bitmap image that displays when the Game Boy is
|
||||||
|
* turned on. It must be intact, or the game will not boot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: global checksums at 0x14D–0x14F, They must
|
||||||
|
* also be correct for the game to boot, so we fix them
|
||||||
|
* as well when the -v flag is set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t ninlogo[48] = {
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
fseek(rom, 0x104, SEEK_SET);
|
||||||
|
fwrite(ninlogo, 1, 48, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settitle) {
|
||||||
|
/*
|
||||||
|
* Offset 0x134–0x143: Game Title
|
||||||
|
* This is a sixteen-character game title in ASCII (no high-
|
||||||
|
* bit characters).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: CGB flag at 0x143. The sixteenth character of
|
||||||
|
* the title is co-opted for use as the CGB flag, so they
|
||||||
|
* may conflict.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x134, SEEK_SET);
|
||||||
|
fwrite(title, 1, strlen(title) + 1, rom);
|
||||||
|
|
||||||
|
while (ftell(rom) < 0x143)
|
||||||
|
fputc(0, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorcompatible) {
|
||||||
|
/*
|
||||||
|
* Offset 0x143: Game Boy Color Flag
|
||||||
|
* If bit 7 is set, the ROM has Game Boy Color features.
|
||||||
|
* If bit 6 is also set, the ROM is for the Game Boy Color
|
||||||
|
* only. (However, this is not actually enforced by the
|
||||||
|
* Game Boy.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: Game Title at 0x134–0x143. The sixteenth
|
||||||
|
* character of the title overlaps with this flag, so they
|
||||||
|
* may conflict.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t byte;
|
||||||
|
|
||||||
|
fseek(rom, 0x143, SEEK_SET);
|
||||||
|
byte = fgetc(rom);
|
||||||
|
|
||||||
|
byte |= 1 << 7;
|
||||||
|
if (coloronly)
|
||||||
|
byte |= 1 << 6;
|
||||||
|
|
||||||
|
if (byte & 0x3F)
|
||||||
|
warnx("Color flag conflicts with game title");
|
||||||
|
|
||||||
|
fseek(rom, 0x143, SEEK_SET);
|
||||||
|
fputc(byte, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setnewlicensee) {
|
||||||
|
/*
|
||||||
|
* Offset 0x144–0x145: New Licensee Code
|
||||||
|
* This is a two-character code identifying which company
|
||||||
|
* created the game.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: the original Licensee ID at 0x14B.
|
||||||
|
* This is deprecated and in all newer games is used instead
|
||||||
|
* as a Super Game Boy flag.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x144, SEEK_SET);
|
||||||
|
fwrite(newlicensee, 1, 2, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (super) {
|
||||||
|
/*
|
||||||
|
* Offset 0x146: Super Game Boy Flag
|
||||||
|
* If not equal to 3, Super Game Boy functions will be
|
||||||
|
* disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: the original Licensee ID at 0x14B.
|
||||||
|
* If the Licensee code is not equal to 0x33, Super Game Boy
|
||||||
|
* functions will be disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!setlicensee)
|
||||||
|
warnx("You should probably set both '-s' and "
|
||||||
|
"'-l 0x33'");
|
||||||
|
|
||||||
|
fseek(rom, 0x146, SEEK_SET);
|
||||||
|
fputc(3, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setcartridge) {
|
||||||
|
/*
|
||||||
|
* Offset 0x147: Cartridge Type
|
||||||
|
* Identifies whether the ROM uses a memory bank controller,
|
||||||
|
* external RAM, timer, rumble, or battery.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x147, SEEK_SET);
|
||||||
|
fputc(cartridge, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resize) {
|
||||||
|
/*
|
||||||
|
* Offset 0x148: Cartridge Size
|
||||||
|
* Identifies the size of the cartridge ROM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We will pad the ROM to match the size given in the header. */
|
||||||
|
int romsize, newsize, headbyte;
|
||||||
|
fseek(rom, 0, SEEK_END);
|
||||||
|
romsize = ftell(rom);
|
||||||
|
newsize = 0x8000;
|
||||||
|
|
||||||
|
headbyte = 0;
|
||||||
|
while (romsize > newsize) {
|
||||||
|
newsize <<= 1;
|
||||||
|
headbyte++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (newsize != ftell(rom)) /* ROM needs resizing */
|
||||||
|
fputc(padvalue, rom);
|
||||||
|
|
||||||
|
if (newsize > 0x800000) /* ROM is bigger than 8MiB */
|
||||||
|
warnx("ROM size is bigger than 8MiB");
|
||||||
|
|
||||||
|
fseek(rom, 0x148, SEEK_SET);
|
||||||
|
fputc(headbyte, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setramsize) {
|
||||||
|
/*
|
||||||
|
* Offset 0x149: RAM Size
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x149, SEEK_SET);
|
||||||
|
fputc(ramsize, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonjapan) {
|
||||||
|
/*
|
||||||
|
* Offset 0x14A: Non-Japanese Region Flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x14A, SEEK_SET);
|
||||||
|
fputc(1, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setlicensee) {
|
||||||
|
/*
|
||||||
|
* Offset 0x14B: Licensee Code
|
||||||
|
* This identifies which company created the game.
|
||||||
|
*
|
||||||
|
* This byte is deprecated and should be set to 0x33 in new
|
||||||
|
* releases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also: the New Licensee ID at 0x144–0x145.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x14B, SEEK_SET);
|
||||||
|
fputc(licensee, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setversion) {
|
||||||
|
/*
|
||||||
|
* Offset 0x14C: Mask ROM Version Number
|
||||||
|
* Which version of the ROM this is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fseek(rom, 0x14C, SEEK_SET);
|
||||||
|
fputc(version, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validate) {
|
||||||
|
/*
|
||||||
|
* Offset 0x14D: Header Checksum
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t headcksum;
|
||||||
|
|
||||||
|
headcksum = 0;
|
||||||
|
fseek(rom, 0x134, SEEK_SET);
|
||||||
|
for (int i = 0; i < (0x14D - 0x134); ++i)
|
||||||
|
headcksum = headcksum - fgetc(rom) - 1;
|
||||||
|
|
||||||
|
fseek(rom, 0x14D, SEEK_SET);
|
||||||
|
fputc(headcksum, rom);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset 0x14E–0x14F: Global Checksum
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t globalcksum;
|
||||||
|
|
||||||
|
globalcksum = 0;
|
||||||
|
|
||||||
|
rewind(rom);
|
||||||
|
for (int i = 0; i < 0x14E; ++i)
|
||||||
|
globalcksum += fgetc(rom);
|
||||||
|
|
||||||
|
int byte;
|
||||||
|
fseek(rom, 0x150, SEEK_SET);
|
||||||
|
while ((byte = fgetc(rom)) != EOF)
|
||||||
|
globalcksum += byte;
|
||||||
|
|
||||||
|
fseek(rom, 0x14E, SEEK_SET);
|
||||||
|
fputc(globalcksum >> 8, rom);
|
||||||
|
fputc(globalcksum & 0xFF, rom);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(rom);
|
fclose(rom);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user