start mering patcher

This commit is contained in:
Romain Dolbeau
2023-08-01 10:12:18 +02:00
parent 17681ccb01
commit ebf13784d2
9 changed files with 416 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1 @@
0x0464e2, 10, removecheksumcheck

View File

@@ -0,0 +1,12 @@
.section .text.removecheksumcheck
nops:
nop
nop
nop
nop
nop
.section .text.returnremovecheksumcheck
.end

View File

@@ -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:

View File

@@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#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;
}

View File

@@ -0,0 +1,10 @@
#ifndef __PATCHER_H__
#define __PATCHER_H__
typedef struct {
unsigned long address;
unsigned long size;
char* name;
} azone;
#endif // __PATCHER_H__

View File

@@ -0,0 +1,34 @@
%{
/*
* Copyright (c) 2023 Romain Dolbeau <romain@dolbeau.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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}+ { }
%%

View File

@@ -0,0 +1,46 @@
%{
/*
* Copyright (c) 2023 Romain Dolbeau <romain@dolbeau.org>
* MIT License
* See the LICENSE file at the top level of this software distribution for details.
*/
#include <stdio.h>
#include <stdlib.h>
#define YYDEBUG 1
#include "parser.h"
%}
%parse-param {azone *zones} {int *nz}
%union
{
unsigned long num;
char* string;
}
%token <num> NUM
%token <num> 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);
}

View File

@@ -0,0 +1,146 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#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;
}