From ebf13784d2e8bd8ac9b1a3ed29039e4dda28a8f8 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Tue, 1 Aug 2023 10:12:18 +0200 Subject: [PATCH] start mering patcher --- RomPatcher/IIsiRemoveChecksumCheck/Makefile | 41 +++++ RomPatcher/IIsiRemoveChecksumCheck/input.txt | 1 + RomPatcher/IIsiRemoveChecksumCheck/rompatch.s | 12 ++ RomPatcher/patcher/Makefile | 50 ++++++ RomPatcher/patcher/genlink.c | 76 +++++++++ RomPatcher/patcher/parser.h | 10 ++ RomPatcher/patcher/parser_lex.l | 34 ++++ RomPatcher/patcher/parser_par.y | 46 ++++++ RomPatcher/patcher/patcher.c | 146 ++++++++++++++++++ 9 files changed, 416 insertions(+) create mode 100644 RomPatcher/IIsiRemoveChecksumCheck/Makefile create mode 100644 RomPatcher/IIsiRemoveChecksumCheck/input.txt create mode 100644 RomPatcher/IIsiRemoveChecksumCheck/rompatch.s create mode 100644 RomPatcher/patcher/Makefile create mode 100644 RomPatcher/patcher/genlink.c create mode 100644 RomPatcher/patcher/parser.h create mode 100644 RomPatcher/patcher/parser_lex.l create mode 100644 RomPatcher/patcher/parser_par.y create mode 100644 RomPatcher/patcher/patcher.c diff --git a/RomPatcher/IIsiRemoveChecksumCheck/Makefile b/RomPatcher/IIsiRemoveChecksumCheck/Makefile new file mode 100644 index 0000000..50ff088 --- /dev/null +++ b/RomPatcher/IIsiRemoveChecksumCheck/Makefile @@ -0,0 +1,41 @@ +RETRO68=/home/dolbeau/Retro68/build/toolchain +AS=${RETRO68}/bin/m68k-apple-macos-as +CC=${RETRO68}/bin/m68k-apple-macos-gcc +LD=${RETRO68}/bin/m68k-apple-macos-ld +STRIP=${RETRO68}/bin/m68k-apple-macos-strip +OBJCOPY=${RETRO68}/bin/m68k-apple-macos-objcopy +NM=${RETRO68}/bin/m68k-apple-macos-nm + +HOSTCC=gcc +HOSTCFLAGS=-O2 + +ARCHFLAGS=-march=68020 -mcpu=68020 +CFLAGS=-O2 -mpcrel + +GENLINK=../patcher/genlink +PATCHER=../patcher/patcher + +all: IIsi.ROM + +show: rompatch.elf + $(NM) $< | sort + +IIsi.ROM: ../IIsi.ROM rompatch.raw input.txt + /bin/cp ../IIsi.ROM IIsi.ROM + ${PATCHER} -i rompatch.raw -p IIsi.ROM -d input.txt + +linker.ld: input.txt rompatch.s + ${GENLINK} -d $< >| $@ + $(shell for X in `grep .section rompatch.s | awk '{ print $$2 }' `; do grep -q $$X linker.ld || echo " $$X has no entry in linker.ld" && /bin/false; done) + +rompatch.o: rompatch.s + ${AS} ${ARCHFLAGS} $< -o $@ -a > rompatch.l + +rompatch.elf: linker.ld rompatch.o ${CSRC:.c=.o} # linker script must be first + ${LD} -o $@ -T $^ + +rompatch.raw: rompatch.elf + ${OBJCOPY} $^ $@ --input-target=elf32-m68k --output-target=binary + +clean: + rm -f res.inc ${CSRC_ASM} *.o rompatch.srec rompatch.raw rompatch.dir rompatch.l VidRom*.s diff --git a/RomPatcher/IIsiRemoveChecksumCheck/input.txt b/RomPatcher/IIsiRemoveChecksumCheck/input.txt new file mode 100644 index 0000000..624c175 --- /dev/null +++ b/RomPatcher/IIsiRemoveChecksumCheck/input.txt @@ -0,0 +1 @@ +0x0464e2, 10, removecheksumcheck diff --git a/RomPatcher/IIsiRemoveChecksumCheck/rompatch.s b/RomPatcher/IIsiRemoveChecksumCheck/rompatch.s new file mode 100644 index 0000000..44149fc --- /dev/null +++ b/RomPatcher/IIsiRemoveChecksumCheck/rompatch.s @@ -0,0 +1,12 @@ + .section .text.removecheksumcheck + +nops: + nop + nop + nop + nop + nop + + .section .text.returnremovecheksumcheck + + .end diff --git a/RomPatcher/patcher/Makefile b/RomPatcher/patcher/Makefile new file mode 100644 index 0000000..49dd775 --- /dev/null +++ b/RomPatcher/patcher/Makefile @@ -0,0 +1,50 @@ +PATCHERSRC=patcher.c +PATCHEROBJ=$(PATCHERSRC:.cpp=.o) +PATCHERDEP=$(PATCHERSRC:.cpp=.d) +GENLINKSRC=genlink.c +GENLINKOBJ=$(GENLINKSRC:.cpp=.o) +GENLINKDEP=$(GENLINKSRC:.cpp=.d) +OOBJ=parser_par.o parser_lex.o +LEX=flex +YACC=bison -d #--report-file=bison.log --report=all +CC=gcc +CFLAGS=-O2 + +all: patcher genlink + +%.o: %.c + $(CC) $(CFLAGS) $< -c -o $@ + +patcher: $(PATCHEROBJ) $(OOBJ) + $(CC) $(CFLAGS) $^ -o $@ + +genlink: $(GENLINKOBJ) $(OOBJ) + $(CC) $(CFLAGS) $^ -o $@ + +parser_par.h: parser_par.o + +parser_par.o: parser_par.y + $(YACC) -o $(<:%.y=%.c) $< + $(CC) $(CFLAGS) $(<:%.y=%.c) -c -o $@ + +parser_lex.o: parser_lex.l parser_par.h + $(LEX) -o $(<:%.l=%.c) $< + $(CC) $(CFLAGS) $(<:%.l=%.c) -c -o $@ + +%.d: %.cpp + $(CXX) -MM $< -o $@ + +clean: + rm -f $(PATCHEROBJ) patcher + +veryclean: + rm -f $(PATCHEROBJ) patcher *~ parser_lex.c parser_par.c *.d + +ultraclean: + rm -f $(PATCHEROBJ) patcher *~ parser_lex.c parser_par.c *.d *.scala + + +## avoid builtin rule for .o +.SUFFIXES: +SUFFIXES := +%.o: diff --git a/RomPatcher/patcher/genlink.c b/RomPatcher/patcher/genlink.c new file mode 100644 index 0000000..68d6a5e --- /dev/null +++ b/RomPatcher/patcher/genlink.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parser.h" +#include "parser_par.h" + +extern FILE *yyin, *yyout; +extern int yydebug; + + +int main(int argc, char **argv) { + char* descfile = NULL; + FILE *myfile; + int c; + azone zones[32]; + int nz = 0, i; + + while ((c = getopt(argc, argv, "d:")) != -1) { + switch(c) { + default: + fprintf(stderr, "oups : %c\n", c); + exit(-1); + break; + + case 'd': + descfile = strndup(optarg, 512); + break; + } + } + + if (descfile == NULL) { + fprintf(stderr, "no desc\n"); + exit(-4); + } + + { + myfile = fopen(descfile, "r"); + if (!myfile) { + fprintf(stderr, "no desc file\n"); + exit(-5); + } + yyin = myfile; + yyparse(zones, &nz); + + fclose(myfile); + + fprintf(stderr, "Found %d entries\n", nz); + } + + fprintf(stdout, + "OUTPUT_FORMAT(\"elf32-m68k\");\n" + "SECTIONS {\n" + " .text : {\n"); + + for (i = 0 ; i < nz; i++) { + fprintf(stdout, " . = 0x%06x;\n", zones[i].address); + fprintf(stdout, " *(.text.%s)\n", zones[i].name); + if (zones[i].size > 0) { + fprintf(stdout, " . = 0x%06x;\n", zones[i].address + zones[i].size); + fprintf(stdout, " *(.text.return%s)\n", zones[i].name); + } + fprintf(stdout, "\n"); + } + + fprintf(stdout, " }\n}\n"); + + return 0; +} diff --git a/RomPatcher/patcher/parser.h b/RomPatcher/patcher/parser.h new file mode 100644 index 0000000..c7f4431 --- /dev/null +++ b/RomPatcher/patcher/parser.h @@ -0,0 +1,10 @@ +#ifndef __PATCHER_H__ +#define __PATCHER_H__ + +typedef struct { + unsigned long address; + unsigned long size; + char* name; +} azone; + +#endif // __PATCHER_H__ diff --git a/RomPatcher/patcher/parser_lex.l b/RomPatcher/patcher/parser_lex.l new file mode 100644 index 0000000..ed42741 --- /dev/null +++ b/RomPatcher/patcher/parser_lex.l @@ -0,0 +1,34 @@ +%{ +/* + * Copyright (c) 2023 Romain Dolbeau + */ +#include +#include +#include + +#include "parser.h" +#include "parser_par.h" +%} + +DIGIT [0-9] +HEXPREFIX "0x" +HEXDIGIT [0-9a-fA-F] +SPACE [ \t] +FCHARNAME [[:alpha:]] +CHARNAME [[:alnum:]_] + +%% + +{HEXPREFIX}{HEXDIGIT}{HEXDIGIT}* { yylval.num = strtol(yytext, NULL, 16); return NUM; } + +{DIGIT}{DIGIT}* { yylval.num = strtol(yytext, NULL, 10); return NUM; } + +{FCHARNAME}{CHARNAME}* { yylval.string = strdup(yytext); return NAME; } + +, { return yytext[0]; } + +\n { return yytext[0]; } + +{SPACE}+ { } + +%% diff --git a/RomPatcher/patcher/parser_par.y b/RomPatcher/patcher/parser_par.y new file mode 100644 index 0000000..6f48d28 --- /dev/null +++ b/RomPatcher/patcher/parser_par.y @@ -0,0 +1,46 @@ +%{ +/* + * Copyright (c) 2023 Romain Dolbeau + * MIT License + * See the LICENSE file at the top level of this software distribution for details. + */ +#include +#include +#define YYDEBUG 1 +#include "parser.h" +%} + +%parse-param {azone *zones} {int *nz} + +%union +{ + unsigned long num; + char* string; +} + +%token NUM +%token NAME + +%% +input: /* empty */ { } +| zone input { } +; + +zone: +NUM ',' NUM ',' NAME { /* printf("0x%08lx %ld\n", $1, $3); */ zones[*nz].address = $1; zones[*nz].size = $3; zones[*nz].name = $5; (*nz)++; } +| '\n' +; +%% + +int +yyerror(char *s) +{ + fprintf(stderr, "error: %s\n", s); + return(0); +} + +int +yywrap(void) +{ + return(-1); +} diff --git a/RomPatcher/patcher/patcher.c b/RomPatcher/patcher/patcher.c new file mode 100644 index 0000000..88af267 --- /dev/null +++ b/RomPatcher/patcher/patcher.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parser.h" +#include "parser_par.h" + +extern FILE *yyin, *yyout; +extern int yydebug; + + +int main(int argc, char **argv) { + char* descfile = NULL; + char* patchedfile = NULL; + char* inputfile = NULL; + FILE *myfile; + int c; + azone zones[32]; + int nz = 0, i; + unsigned long j; + char *input; + size_t input_size; + char *patched; + size_t patched_size; + + while ((c = getopt(argc, argv, "d:i:p:")) != -1) { + switch(c) { + default: + fprintf(stderr, "oups : %c\n", c); + exit(-1); + break; + + case 'd': + descfile = strndup(optarg, 512); + break; + + case 'i': + inputfile = strndup(optarg, 512); + break; + + case 'p': + patchedfile = strndup(optarg, 512); + break; + } + } + + if (descfile == NULL) { + fprintf(stderr, "no desc\n"); + exit(-4); + } + if (inputfile == NULL) { + fprintf(stderr, "no input\n"); + exit(-2); + } + if (patchedfile == NULL) { + fprintf(stderr, "nothing to patch\n"); + exit(-3); + } + + + + { + myfile = fopen(descfile, "r"); + if (!myfile) { + fprintf(stderr, "no desc file\n"); + exit(-5); + } + yyin = myfile; + yyparse(zones, &nz); + + fclose(myfile); + + fprintf(stdout, "Found %d entries\n", nz); + } + + { + int fd; + fd = open(inputfile, O_RDONLY | O_EXCL); + if (fd == -1) { + fprintf(stderr, "no input file\n"); + exit(-6); + } + struct stat statbuf; + int err = fstat(fd, &statbuf); + if (err < 0){ + fprintf(stderr, "no input file stat\n"); + close(fd); + exit(-7); + } + input_size = statbuf.st_size; + input = mmap(NULL, input_size, PROT_READ, MAP_SHARED, fd, 0); + if (input == MAP_FAILED){ + fprintf(stderr, "no input file map (%p for %s %zd: %d / %s)\n", input, inputfile, input_size, errno, strerror(errno)); + close(fd); + exit(-8); + } + close(fd); + } + { + int fd; + fd = open(patchedfile, O_RDWR | O_EXCL); + if (fd == -1) { + fprintf(stderr, "no patched file\n"); + exit(-6); + } + struct stat statbuf; + int err = fstat(fd, &statbuf); + if (err < 0){ + fprintf(stderr, "no patched file stat\n"); + close(fd); + exit(-7); + } + + patched_size = statbuf.st_size; + patched = mmap(NULL, patched_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (patched == MAP_FAILED){ + fprintf(stderr, "no patched file map\n"); + close(fd); + exit(-8); + } + close(fd); + } + + for (i = 0 ; i < nz; i++) { + if (zones[i].size > 0) { + fprintf(stdout, "Patching [%08p:%08p[ (%s)\n", (void*)zones[i].address, (void*)(zones[i].address + zones[i].size), zones[i].name); + for (j = zones[i].address; j < zones[i].address + zones[i].size; j++) { + patched[j] = input[j]; + } + } else { + fprintf(stdout, "Not patching [%08p[ (%s)\n", (void*)zones[i].address, zones[i].name); + } + } + + munmap(input, input_size); + munmap(patched, patched_size); + + return 0; +}