summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chkpar.c98
-rw-r--r--src/exi.c21
-rw-r--r--src/getsum.c25
-rw-r--r--src/hlp.c30
-rw-r--r--src/inidat.c20
-rw-r--r--src/main.c47
-rw-r--r--src/opn.c25
-rw-r--r--src/pat.c22
-rw-r--r--src/red.c23
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);
+ }
+}