Skip to content

Commit

Permalink
ADPATCH rewrite
Browse files Browse the repository at this point in the history
Different patches can now easily refer to each other. Handy when
there's not enough room for a simple patch.

Updated & expanded Miles and LucasArts patches.
  • Loading branch information
pdewacht committed Apr 29, 2019
1 parent f4a4081 commit 64a3654
Show file tree
Hide file tree
Showing 16 changed files with 885 additions and 466 deletions.
3 changes: 2 additions & 1 deletion adpatch/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
adpatch
adpatch.exe
patterns.rl
patch.c
patch.inc
scan.c
*.o
41 changes: 41 additions & 0 deletions adpatch/adpatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#define MAX_MATCHES 8
#define MAX_RELOCATIONS 2
#define MAX_EXPORTS 2

enum relocation_type {
R_386_32,
R_386_PC32,
R_386_16,
R_386_PC16
};

struct relocation {
long offset;
int symbol;
enum relocation_type type;
};

struct export {
int symbol;
int offset;
};

struct patch {
const char *name;
const char *code;
int code_len;
struct relocation rel[MAX_RELOCATIONS];
struct export export[MAX_EXPORTS];
};

struct match {
const struct patch *patch;
long offset;
int len;
};


int apply_patches(FILE *in, FILE *out, int lpt_port);
int scan_and_copy(FILE *in, FILE *out, struct match *matches);

extern const struct patch patch_data[];
9 changes: 5 additions & 4 deletions adpatch/build.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/bin/sh
set -e

VERSION=20181030
VERSION=20190429

CC='wcc -bt=dos -zq -oxhs'
DEFS="-dVERSION=$VERSION"

set -x
python3 genpat.py > patterns.rl
ragel -s -G2 patch.rl
python3 genpat.py
ragel -s -G2 scan.rl
$CC $DEFS main.c
$CC $DEFS patch.c
wlink name adpatch system dos file main,patch option quiet
$CC $DEFS scan.c
wlink name adpatch system dos file main,patch,scan option quiet
6 changes: 3 additions & 3 deletions adpatch/buildgcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ set -e
eval $(grep ^VERSION= build.sh)
DEFS="-DVERSION=$VERSION"

python3 genpat.py > patterns.rl
ragel -s -G2 patch.rl
cc -Wall -O $DEFS -o adpatch main.c patch.c
python3 genpat.py
ragel -s -G2 scan.rl
cc -Wall $DEFS -o adpatch -fsanitize=undefined,address main.c patch.c scan.c
2 changes: 1 addition & 1 deletion adpatch/clean.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
rm -f adpatch adpatch.exe main.o patch.c patch.o patterns.rl
rm -f adpatch adpatch.exe main.o patch.o patch.inc scan.c scan.o patterns.rl
105 changes: 105 additions & 0 deletions adpatch/elf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from collections import namedtuple
import struct


ElfHeader = namedtuple(
'ElfHeader',
'e_ident e_type e_machine e_version e_entry e_phoff e_shoff e_flags '
'e_ehsize e_phentsize e_phnum e_shentsize e_shnum e_shstrndx')


SectionHeader = namedtuple(
'SectionHeader',
'sh_name sh_type sh_flags sh_addr sh_offset sh_size sh_link sh_info '
'sh_addralign sh_entsize')


SymbolTableEntry = namedtuple(
'SymbolTableEntry',
'st_name st_value st_size st_info st_other st_shndx')


RelocationEntry = namedtuple(
'RelocationEntry',
'r_offset r_type r_sym')


def parse_elf_header(bs, offset=0):
return ElfHeader(*struct.unpack_from('<16s 2H 5I 6H', bs, offset))


def parse_section_header(bs, offset):
return SectionHeader(*struct.unpack_from('<10I', bs, offset))


def parse_symbol_table_entry(bs, offset):
return SymbolTableEntry(*struct.unpack_from('<3I 2B H', bs, offset))


def parse_relocation_entry(bs, offset):
return RelocationEntry(*struct.unpack(
'<IBI', bs[offset:offset+8] + b'\x00'))


def asciiz(bs, offset):
return bs[offset:bs.index(b'\x00', offset)].decode('ascii')


RELOCATION_TYPES = {
1: 'R_386_32',
2: 'R_386_PC32',
20: 'R_386_16',
21: 'R_386_PC16',
}


def parse(bs):
elf = parse_elf_header(bs)
section_list = [
parse_section_header(bs, elf.e_shoff + i * elf.e_shentsize)
for i in range(elf.e_shnum)
]

def section_name(n):
return asciiz(bs, section_list[elf.e_shstrndx].sh_offset + n)

sections = {section_name(s.sh_name): s for s in section_list}

s = sections['.symtab']
symbols = [
parse_symbol_table_entry(bs, s.sh_offset + i)
for i in range(0, s.sh_size, s.sh_entsize)
]

def symbol_name(sym):
return asciiz(bs, sections['.strtab'].sh_offset + sym.st_name)

exports = {
symbol_name(sym): sym.st_value
for sym in symbols
if sym.st_info & 16 != 0
if section_name(sym.st_shndx) == '.text'
}

if '.rel.text' not in sections:
relocations = []
else:
s = sections['.rel.text']
relocations = [
parse_relocation_entry(bs, s.sh_offset + i)
for i in range(0, s.sh_size, s.sh_entsize)
]

relocations = [
RelocationEntry(
r_offset=rel.r_offset,
r_type=RELOCATION_TYPES[rel.r_type],
r_sym=symbol_name(symbols[rel.r_sym])
)
for rel in relocations
]

s = sections['.text']
text = bs[s.sh_offset:s.sh_offset+s.sh_size]

return (text, exports, relocations)
Loading

0 comments on commit 64a3654

Please sign in to comment.