diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/checkParams.c | 133 | ||||
-rw-r--r-- | source/copyright.c | 49 | ||||
-rw-r--r-- | source/exit.c | 36 | ||||
-rw-r--r-- | source/getSum.c | 40 | ||||
-rw-r--r-- | source/help.c | 46 | ||||
-rw-r--r-- | source/initData.c | 36 | ||||
-rw-r--r-- | source/main.c | 65 | ||||
-rw-r--r-- | source/open.c | 40 | ||||
-rw-r--r-- | source/patch.c | 38 | ||||
-rw-r--r-- | source/read.c | 42 |
10 files changed, 525 insertions, 0 deletions
diff --git a/source/checkParams.c b/source/checkParams.c new file mode 100644 index 0000000..47bdeef --- /dev/null +++ b/source/checkParams.c @@ -0,0 +1,133 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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 <stddef.h> +#include <stdio.h> +#include <string.h> + +noreturn static void +agb_expectedParamValue (char const charParam) +{ + fprintf (stderr, "Expected value for character parameter '%c'\n", charParam); + agb_exit (agb_Cnd_Error, NULL); +} + +static bool +agb_checkCharParam (struct agb_Data* const restrict data, char const* const restrict param) +{ + // Returns true if the rest of the parameter is + // used as a value. + + char const charParam = param[0x0]; + if (charParam == '\x0') {return true;} + + char const* const restrict paramval = ¶m[0x1]; + + switch (charParam) { + default: + fprintf (stderr, "Invalid character parameter '%c'\n", charParam); + agb_exit (agb_Cnd_Error, NULL); + + case 'h': + agb_help (); + agb_exit (agb_Cnd_Ok, NULL); + + case 'i': + { + if (paramval[0x0] == '\x0') {agb_expectedParamValue (charParam);} + data->path = paramval; + } + return true; + + case 'p': + data->doPatch = true; + return false; + + case 's': + data->silent = true; + return false; + } +} + +void +agb_checkParams (struct agb_Data* const restrict data, int const argc, char const* const* const argv) { + if (argc < 0x2) { + agb_help (); + agb_exit (agb_Cnd_Ok, NULL); + } + + size_t const numParams = argc; // Prettier. + + for (ptrdiff_t index = 0x1; index < (ptrdiff_t)numParams; ++index) { + // Iterate over the parameters. One hyphen denotes character parameters (-h) whilst two denote long paramters (--help). + + char const* const param = argv[index]; + if (param[0x0] == '-') { + if (param[0x1] == '-') { + char const* const longParam = ¶m[0x2]; + + // Check long parameters. + + if (longParam[0x0] == '\x0') { + fputs ("Missing long parameter after '--' sequence\n", stderr); + agb_exit (agb_Cnd_Error, NULL); + } + + if (!strcmp (longParam, "help")) { + agb_help (); + agb_exit (agb_Cnd_Ok, NULL); + } + + if (!strcmp (longParam, "version")) { + agb_copyright(); + agb_exit (agb_Cnd_Ok, NULL); + } + + fprintf (stderr, "Invalid long parameter \"%s\"\n", longParam); + agb_exit (agb_Cnd_Error, NULL); + } + + if (param[0x1] == '\x0') { + fputs ("Missing character parameter after '-'\n", stderr); + agb_exit (agb_Cnd_Error, NULL); + } + + // Check character parameters. + + for (char const* charIndex = ¶m[0x1];; ++charIndex) { if (agb_checkCharParam (data, charIndex)) { break; } } + + continue; + } + + // We did not find the 'i' parameter, so we don't know where the ROM is. + + if (data->path == NULL) { + fputs ("ROM not set (missing character parameter 'i')\n", stderr); + agb_exit (agb_Cnd_Error, NULL); + } + } +} diff --git a/source/copyright.c b/source/copyright.c new file mode 100644 index 0000000..14a64a5 --- /dev/null +++ b/source/copyright.c @@ -0,0 +1,49 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_copyright (void) +{ + printf ( + "agbsum #%" PRIX64 " - Copyright 2022-2023 Gabriel Bj\u00F8rnager Jensen.\n" + "\n" + "This program is free software: you can redistribute it and/or modify it under\n" + "the terms of the GNU General Public License as published by the Free Software\n" + "Foundation, either version 3 of the License, or (at your option) any later\n" + "version.\n" + "\n" + "This program is distributed in the hope that it will be useful, but WITHOUT ANY\n" + "WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n" + "PARTICULAR PURPOSE. See the GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License along with\n" + "this program. If not, see <https://www.gnu.org/licenses/>.\n", + agb_release + ); +} diff --git a/source/exit.c b/source/exit.c new file mode 100644 index 0000000..b34d91c --- /dev/null +++ b/source/exit.c @@ -0,0 +1,36 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_exit (enum agb_Condition const condition, FILE* restrict image) +{ + if (image != NULL) { fclose (image); } + + exit (condition == agb_Cnd_Ok ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/source/getSum.c b/source/getSum.c new file mode 100644 index 0000000..6d600ae --- /dev/null +++ b/source/getSum.c @@ -0,0 +1,40 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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 imagePtr) +{ + uint8_t const* restrict image = imagePtr; + uint8_t sum = UINT8_C(0x0); + + for (char unsigned const* restrict position = image; position != image + agb_sumOffset; ++position) { sum += *position; } + + sum = -(UINT8_C(0x19) + sum); + + return sum; +} diff --git a/source/help.c b/source/help.c new file mode 100644 index 0000000..3686af9 --- /dev/null +++ b/source/help.c @@ -0,0 +1,46 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_help (void) +{ + fputs ( + "agbsum - Patch AGB image header checksums.\n" + "\n" + "Usage: agbsum [options] <image>\n" + "Options:\n" + " --help -h Print the help screen\n" + " -p Patch the image file\n" + " -s Don't print results\n" + " --version Print the version number\n" + "\n", + stdout + ); + agb_copyright (); +} diff --git a/source/initData.c b/source/initData.c new file mode 100644 index 0000000..f9baea3 --- /dev/null +++ b/source/initData.c @@ -0,0 +1,36 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_initdata (struct agb_Data* const restrict data) +{ + data->doPatch = false; + data->path = NULL; + data->silent = false; + data->image = NULL; +} diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..4583eb5 --- /dev/null +++ b/source/main.c @@ -0,0 +1,65 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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) +{ + struct agb_Data data; + agb_initdata (&data); + agb_checkParams (&data, argc, argv); + + data.image = agb_open (data.path); + + char unsigned buffer[agb_sumOffset + 0x1]; + + agb_read (buffer, data.image); + + { + char unsigned const sum = agb_getSum (buffer); + char unsigned const imageSum = buffer[agb_sumOffset]; + + if (imageSum == sum || !data.doPatch) { + // Don't patch the ROM if it's already okay or we're not allowed to. + if (!data.silent) {printf ("\"%s\": %hhX (%hhX in file)\n", data.path, sum, imageSum);} + agb_exit (agb_Cnd_Ok, data.image); + } + + agb_patch (data.image, sum); + + // If we aren't supposed to print anything then + // don't. + if (!data.silent) { printf ("\"%s\" @ %zX: %hhX => %hhX\n", data.path, agb_sumDataStart + agb_sumOffset, imageSum, sum); } + } + + agb_exit (agb_Cnd_Ok, data.image); +} diff --git a/source/open.c b/source/open.c new file mode 100644 index 0000000..415e589 --- /dev/null +++ b/source/open.c @@ -0,0 +1,40 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_open (char const* const restrict path) +{ + FILE* image = fopen (path, "r+"); + + if (image == NULL) { + fputs ("Unable to open ROM\n", stderr); + agb_exit (agb_Cnd_Error, NULL); + } + + return image; +} diff --git a/source/patch.c b/source/patch.c new file mode 100644 index 0000000..78d2531 --- /dev/null +++ b/source/patch.c @@ -0,0 +1,38 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_patch (FILE* const restrict image, char unsigned sum) +{ + fseek (image, (long)(agb_sumDataStart + agb_sumOffset), SEEK_SET); + + if (fwrite (&sum, 0x1u, 0x1u, image) != 0x1u) { + fputs ("Unable to patch ROM\n", stderr); + agb_exit (agb_Cnd_Error, image); + } +} diff --git a/source/read.c b/source/read.c new file mode 100644 index 0000000..0ed3808 --- /dev/null +++ b/source/read.c @@ -0,0 +1,42 @@ +/* + Copyright 2022-2023 Gabriel Bjørnager 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_read (void* const restrict buffer, FILE* restrict image) +{ + // We only need to read the part of the image + // that is used for the checksum. + fseek (image, agb_sumDataStart, SEEK_SET); + + size_t const count = agb_sumOffset + 0x1u; + + if (fread (buffer, 0x1u, count, image) != count) { + fputs ("Unable to read ROM\n", stderr); + agb_exit (agb_Cnd_Error, image); + } +} |