diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chkpar.c | 98 | ||||
-rw-r--r-- | src/exi.c | 21 | ||||
-rw-r--r-- | src/getsum.c | 25 | ||||
-rw-r--r-- | src/hlp.c | 30 | ||||
-rw-r--r-- | src/inidat.c | 20 | ||||
-rw-r--r-- | src/main.c | 47 | ||||
-rw-r--r-- | src/opn.c | 25 | ||||
-rw-r--r-- | src/pat.c | 22 | ||||
-rw-r--r-- | src/red.c | 23 |
9 files changed, 311 insertions, 0 deletions
diff --git a/src/chkpar.c b/src/chkpar.c new file mode 100644 index 0000000..9ad487d --- /dev/null +++ b/src/chkpar.c @@ -0,0 +1,98 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +noreturn static void +agb_expparval (char const chrpar) +{ + fprintf (stderr,"Expected value for character parameter '%c'\n", chrpar); + agb_exi (agb_cnd_err, NULL); +} + +static bool +agb_chkchrpar (agb_dat * const restrict dat, char const* const restrict par) +{ + char const chrpar = par[0x0u]; + if (chrpar == '\x0') {return true;} + + char const* const restrict paramval = &par[0x1]; + + switch (chrpar) { + default: + fprintf (stderr,"Invalid character parameter '%c'\n", chrpar); + agb_exi (agb_cnd_err, NULL); + case 'h': + agb_hlp (); + agb_exi (agb_cnd_oky, NULL); + case 'i': + { + if (paramval[0x0u] == '\x0') {agb_expparval (chrpar);} + dat->pth = paramval; + } + return true; + case 'p': + dat->dopat = true; + return false; + case 's': + dat->sil = true; + return false; + } +} + +void +agb_chkpar (agb_dat * const restrict dat, int const argc, char const* const* const argv) { + if (argc < 0x2) { + agb_hlp (); + agb_exi (agb_cnd_oky, NULL); + } else { + size_t const numpar = argc; + + for (size_t pos = 0x1u;pos < numpar;++pos) { + + char const* const par = argv[pos]; + if (par[0x0u] == '-') { + if (par[0x1u] == '-') { + char const* const lngparam = &par[0x2u]; + + if (lngparam[0x0u] == '\x0') { + fputs ("Missing long parameter after '--' sequence\n", stderr); + agb_exi (agb_cnd_err, NULL); + } + + if (!strcmp (lngparam,"help")) { + agb_hlp (); + agb_exi (agb_cnd_oky, NULL); + } + + fprintf (stderr,"Invalid long parameter \"%s\"\n", lngparam); + agb_exi (agb_cnd_err, NULL); + } + + if (par[0x1u] == '\x0') { + fputs ("Missing character parameter after '-'\n", stderr); + agb_exi (agb_cnd_err, NULL); + } + + for (char const* chrpos = &par[0x1u];;++chrpos) {if (agb_chkchrpar (dat, chrpos)) {break;}} + + continue; + } + } + + if (dat->pth == NULL) { + fputs ("ROM not set (missing character parameter 'i')\n", stderr); + agb_exi (agb_cnd_err, NULL); + } + } +} diff --git a/src/exi.c b/src/exi.c new file mode 100644 index 0000000..54514c0 --- /dev/null +++ b/src/exi.c @@ -0,0 +1,21 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stdio.h> +#include <stdlib.h> + +noreturn void +agb_exi (agb_cnd const cnd, FILE * restrict rom) +{ + if (rom != NULL) {fclose (rom);} + + exit (cnd == agb_cnd_oky ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/src/getsum.c b/src/getsum.c new file mode 100644 index 0000000..b92fdef --- /dev/null +++ b/src/getsum.c @@ -0,0 +1,25 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stdint.h> + +uint8_t +agb_getsum (void const* const restrict romptr) +{ + uint8_t const* restrict rom = romptr; + uint8_t chksum = 0x0u; + + for (unsigned char const* restrict pos = rom;pos != rom+agb_chksumoff;++pos) {chksum += *pos;} + + chksum = 0x0u-(0x19u+chksum); + + return chksum; +} diff --git a/src/hlp.c b/src/hlp.c new file mode 100644 index 0000000..63a5c08 --- /dev/null +++ b/src/hlp.c @@ -0,0 +1,30 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <inttypes.h> +#include <stdio.h> + +void +agb_hlp (void) +{ + fprintf (stderr, + "agbsum - Calculate GBA ROM header checksums.\n" + "Release #%" PRIX64 ". Copyright 2022-2023 Gabriel Jensen.\n" + "\n" + "Usage: agbsum [options] <ROM>\n" + "Options:\n" + " --help -h Print the help screen\n" + " -p Patch the ROM\n" + " -s Don't print the results\n" + "\n", + agb_rel + ); +} diff --git a/src/inidat.c b/src/inidat.c new file mode 100644 index 0000000..0657c70 --- /dev/null +++ b/src/inidat.c @@ -0,0 +1,20 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stddef.h> + +void agb_inidat (agb_dat * const restrict dat) +{ + dat->dopat = false; + dat->pth = NULL; + dat->sil = false; + dat->rom = NULL; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..44d8a96 --- /dev/null +++ b/src/main.c @@ -0,0 +1,47 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <limits.h> +#include <stdint.h> +#include <stdio.h> + +#if CHAR_BIT != 0x8 +#error "agbsum only support 8-bit byte systems" +#endif + +int main (int const argc, char const* const* const argv) +{ + agb_dat dat; + + agb_inidat (&dat); + + agb_chkpar (&dat, argc, argv); + + dat.rom = agb_opn (dat.pth); + + unsigned char buf[agb_chksumoff+0x1u]; + + agb_red (buf, dat.rom); + + unsigned char const chksum = agb_getsum (buf); + unsigned char const romchksum = buf[agb_chksumoff]; + + if (romchksum == chksum || !dat.dopat) { + if (!dat.sil) {printf ("\"%s\": %hhX (%hhX in file)\n", dat.pth, chksum, romchksum);} + agb_exi (agb_cnd_oky, dat.rom); + } + + agb_pat (dat.rom, chksum); + + if (!dat.sil) {printf ("\"%s\" @ %zX: %hhX => %hhX\n", dat.pth, agb_romsrt+agb_chksumoff, romchksum, chksum);} + + agb_exi (agb_cnd_oky, dat.rom); +} diff --git a/src/opn.c b/src/opn.c new file mode 100644 index 0000000..964e14c --- /dev/null +++ b/src/opn.c @@ -0,0 +1,25 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stdio.h> + +FILE * +agb_opn (char const* const restrict pth) +{ + FILE * rom = fopen (pth,"r+"); + + if (rom == NULL) { + fputs ("Unable to open ROM\n", stderr); + agb_exi (agb_cnd_err, NULL); + } + + return rom; +} diff --git a/src/pat.c b/src/pat.c new file mode 100644 index 0000000..9313665 --- /dev/null +++ b/src/pat.c @@ -0,0 +1,22 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stdio.h> + +void agb_pat (FILE * const restrict rom, unsigned char chksum) +{ + fseek (rom,(long)(agb_romsrt+agb_chksumoff), SEEK_SET); + + if (fwrite (&chksum,0x1u,0x1u, rom) != 0x1u) { + fputs ("Unable to patch ROM\n", stderr); + agb_exi (agb_cnd_err, rom); + } +} diff --git a/src/red.c b/src/red.c new file mode 100644 index 0000000..da9b5af --- /dev/null +++ b/src/red.c @@ -0,0 +1,23 @@ +/* + Copyright 2022-2023 Gabriel Jensen. + + This file is part of agbsum. + agbsum is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + agbsum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License along with agbsum. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <agbsum.h> + +#include <stdio.h> + +void agb_red (void * const restrict buf, FILE * restrict rom) +{ + fseek (rom, agb_romsrt, SEEK_SET); // We only need to read the part of the ROM that is used for the checksum. + size_t const num = agb_chksumoff+0x1u; + + if (fread (buf,0x1u, num, rom) != num) { + fputs ("Unable to read ROM\n", stderr); + agb_exi (agb_cnd_err, rom); + } +} |