Add Saturn toolchain (#234)

This adds some new Makefile commands:

build_saturn_toolchain: Downloads GCCSH, and builds two docker
containers. One container is binutils for SuperH, and the other has
Dosemu.

build_saturn: Copies GCCSH, the source code, and asm into the build
directory and runs the GCCSH via Dosemu in the docker container.
Everything is kept in the same directory since it's hard to use Dosemu
otherwise.

check_saturn: Dumps the object files to binary using the binutils Docker
container, then checks the hashes.

diff_saturn: Compares the binaries and outputs a diff to
build/saturn/$FILENAME-diff.txt. Used like FILENAME=GAME.PRG make
diff_saturn.

I've added the source for game.c and t_bat.c. I've replaced one of the
asm functions in t_bat.c to show that it's possible to match simple
functions. I'm not able to generate linker scripts yet so functions that
rely on symbols from other overlays generally can't be matched yet.

This workflow is not all that clean so I'm open to ideas on improving
it. I tried using various versions of
https://github.com/decompals/old-gcc to try to get a native compiler but
couldn't get a matching build. I'm not 100% sure that this version of
GCCSH is correct but initial results seem promising.

As of right now, it's not possible to run this in CI since the dosemu
container changes the USER and Github won't let you write to disk if you
do that.
https://docs.github.com/en/actions/creating-actions/dockerfile-support-for-github-actions#user
This commit is contained in:
sozud 2023-06-03 11:09:44 -07:00 committed by GitHub
parent c599ee3cf4
commit 859230a25d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 584 additions and 1 deletions

1
.gitignore vendored
View File

@ -32,3 +32,4 @@ disks/
.vscode/settings.json .vscode/settings.json
tools/go tools/go
tools/saturn_toolchain/GCCSH

View File

@ -253,6 +253,7 @@ $(CONFIG_DIR)/generated.$(VERSION).symbols.%.txt:
extract_saturn: $(SATURN_SPLITTER_APP) extract_saturn: $(SATURN_SPLITTER_APP)
$(SATURN_SPLITTER_APP) $(CONFIG_DIR)/saturn/game.prg.yaml $(SATURN_SPLITTER_APP) $(CONFIG_DIR)/saturn/game.prg.yaml
$(SATURN_SPLITTER_APP) $(CONFIG_DIR)/saturn/t_bat.prg.yaml $(SATURN_SPLITTER_APP) $(CONFIG_DIR)/saturn/t_bat.prg.yaml
$(SATURN_SPLITTER_APP) $(CONFIG_DIR)/saturn/zero.bin.yaml
# Force to extract all the assembly code regardless if a function is already decompiled # Force to extract all the assembly code regardless if a function is already decompiled
force_extract: force_extract:
@ -348,6 +349,76 @@ $(BUILD_DIR)/%.s.o: %.s
$(BUILD_DIR)/%.c.o: %.c $(ASPATCH) $(CC1PSX) $(BUILD_DIR)/%.c.o: %.c $(ASPATCH) $(CC1PSX)
$(CPP) $(CPP_FLAGS) $< | $(CC) $(CC_FLAGS) | $(ASPATCH) | $(AS) $(AS_FLAGS) -o $@ $(CPP) $(CPP_FLAGS) $< | $(CC) $(CC_FLAGS) | $(ASPATCH) | $(AS) $(AS_FLAGS) -o $@
build_saturn_toolchain:
# get GCCSH
wget -nc https://github.com/sozud/saturn-compilers/archive/refs/heads/main.zip
unzip -n main.zip
rm -rf ./tools/saturn_toolchain/GCCSH
mv saturn-compilers-main/cygnus-2.7-96Q3-bin ./tools/saturn_toolchain/GCCSH
rm -rf main.zip
rm -rf saturn-compilers-main
# build dockerfiles
docker build -t dosemu:latest -f tools/saturn_toolchain/dosemu_dockerfile .
docker build -t binutils-sh-elf:latest -f tools/saturn_toolchain/binutils_dockerfile .
SATURN_BUILD_DIR := build/saturn
# absolute path for docker mounts
SATURN_BUILD_ABS := $(realpath $(SATURN_BUILD_DIR))
SATURN_DISK_DIR := disks/saturn
# absolute path for docker mounts
SATURN_DISK_ABS := $(realpath $(SATURN_DISK_DIR))
build_saturn:
# copy everything into same directory since dosemu is hard to use otherwise
rm -rf $(SATURN_BUILD_DIR)
mkdir -p $(SATURN_BUILD_DIR)
cp -r ./tools/saturn_toolchain/GCCSH/* $(SATURN_BUILD_DIR)
cp ./src/saturn/inc_asm.h $(SATURN_BUILD_DIR)
cp ./src/saturn/macro.inc $(SATURN_BUILD_DIR)
cp ./src/saturn/game.c $(SATURN_BUILD_DIR)
cp ./src/saturn/t_bat.c $(SATURN_BUILD_DIR)
cp ./src/saturn/zero.c $(SATURN_BUILD_DIR)
mkdir -p $(SATURN_BUILD_DIR)/asm/saturn/
mkdir -p $(SATURN_BUILD_DIR)/asm/saturn/
cp -r ./asm/saturn/game $(SATURN_BUILD_DIR)/asm/saturn/game
cp -r ./asm/saturn/t_bat $(SATURN_BUILD_DIR)/asm/saturn/t_bat
cp -r ./asm/saturn/zero $(SATURN_BUILD_DIR)/asm/saturn/zero
cp ./tools/saturn_toolchain/compile_dosemu.sh $(SATURN_BUILD_DIR)
chmod +x $(SATURN_BUILD_DIR)/compile_dosemu.sh
# execute in docker
docker run --rm -e FILENAME=game -v $(SATURN_BUILD_ABS):/build -w /build dosemu:latest /bin/bash -c "./compile_dosemu.sh"
docker run --rm -e FILENAME=t_bat -v $(SATURN_BUILD_ABS):/build -w /build dosemu:latest /bin/bash -c "./compile_dosemu.sh"
docker run --rm -e FILENAME=zero -v $(SATURN_BUILD_ABS):/build -w /build dosemu:latest /bin/bash -c "./compile_dosemu.sh"
# link
cat ./config/saturn/game_syms.txt > ./build/saturn/all_syms.txt
cat ./config/saturn/t_bat_syms.txt >> ./build/saturn/all_syms.txt
cat ./config/saturn/zero_syms.txt >> ./build/saturn/all_syms.txt
cp ./config/saturn/t_bat_user_syms.txt ./build/saturn/
cp ./config/saturn/game_user_syms.txt ./build/saturn/
cp ./config/saturn/*.ld ./build/saturn
docker run --rm -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c "sh-elf-ld -o zero_li.o -Map zero.map -T zero.ld -T all_syms.txt -verbose zero.o --no-check-sections -nostdlib -s"
docker run --rm -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c "sh-elf-ld -o t_bat_li.o -Map t_bat.map -T t_bat.ld -T all_syms.txt -T t_bat_user_syms.txt -verbose t_bat.o --no-check-sections -nostdlib -s"
docker run --rm -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c "sh-elf-ld -o game_li.o -Map game.map -T game.ld -T all_syms.txt -T game_user_syms.txt -verbose game.o --no-check-sections -nostdlib -s"
check_saturn:
# dump binaries using sh binutils container
chmod +x tools/saturn_toolchain/strip.sh
cp tools/saturn_toolchain/strip.sh $(SATURN_BUILD_DIR)
docker run --rm -e INPUT_FILENAME=game_li.o -e OUTPUT_FILENAME=GAME.PRG -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c ./strip.sh
docker run --rm -e INPUT_FILENAME=t_bat_li.o -e OUTPUT_FILENAME=T_BAT.PRG -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c ./strip.sh
docker run --rm -e INPUT_FILENAME=zero_li.o -e OUTPUT_FILENAME=0.BIN -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c ./strip.sh
# check hashes
sha1sum --check config/saturn/check.saturn.sha
diff_saturn:
chmod +x tools/saturn_toolchain/diff.sh
cp tools/saturn_toolchain/diff.sh $(SATURN_BUILD_DIR)
docker run --rm -e FILENAME=$(FILENAME) -v $(SATURN_DISK_ABS):/theirs -v $(SATURN_BUILD_ABS):/build -w /build binutils-sh-elf:latest /bin/bash -c ./diff.sh
# Handles assets # Handles assets
$(BUILD_DIR)/$(ASSETS_DIR)/%.layoutobj.json.o: $(ASSETS_DIR)/%.layoutobj.json $(BUILD_DIR)/$(ASSETS_DIR)/%.layoutobj.json.o: $(ASSETS_DIR)/%.layoutobj.json
./tools/splat_ext/layoutobj.py $< $(BUILD_DIR)/$(ASSETS_DIR)/$*.bin ./tools/splat_ext/layoutobj.py $< $(BUILD_DIR)/$(ASSETS_DIR)/$*.bin

View File

@ -0,0 +1,3 @@
f03234c4f21819d30d34b05aaa7e352702dca0dc build/saturn/GAME.PRG
d513a3a1fcab77dcb792fedfe974434c80591328 build/saturn/T_BAT.PRG
54c2e3e59f9f627bc0df6d9ab5acff4987fa4722 build/saturn/0.BIN

View File

@ -2,6 +2,8 @@ options:
target_path: disks/saturn/GAME.PRG target_path: disks/saturn/GAME.PRG
asm_path: asm/saturn/game asm_path: asm/saturn/game
src_path: src/saturn src_path: src/saturn
ld_scripts_path: config/saturn
syms_path: config/saturn
# some sort of alignment issues # some sort of alignment issues
decomp_empty_funcs: false decomp_empty_funcs: false
segments: segments:

View File

@ -0,0 +1 @@
_g_randomNext = 0x0605D748;

View File

@ -2,6 +2,8 @@ options:
target_path: disks/saturn/T_BAT.PRG target_path: disks/saturn/T_BAT.PRG
asm_path: asm/saturn/t_bat asm_path: asm/saturn/t_bat
src_path: src/saturn src_path: src/saturn
ld_scripts_path: config/saturn
syms_path: config/saturn
decomp_empty_funcs: true decomp_empty_funcs: true
segments: segments:
- name: t_bat - name: t_bat

View File

@ -0,0 +1 @@
_D_80174D3C = 0x060D1DFC;

View File

@ -0,0 +1,51 @@
options:
target_path: disks/saturn/0.BIN
asm_path: asm/saturn/zero
src_path: src/saturn
ld_scripts_path: config/saturn
syms_path: config/saturn
decomp_empty_funcs: false
segments:
- name: zero
type: code
start: 0x00000000
vram: 0x06004080
subalign: 2
subsegments:
- start: 0x0
type: data
file: zero
end: 0xae07
# ratan2
- start: 0xae08
type: c
file: zero
end: 0xaf3b
- start: 0xaf3c
type: data
file: zero
end: 0xb893
# squareroot12
- start: 0xB894
type: c
file: zero
end: 0xb8eb
- start: 0xb8ec
type: data
file: zero
end: 0xbf37
# DestroyEntity
- start: 0xBf38
type: c
file: zero
end: 0xbf87
- start: 0xbf88
type: data
file: zero
end: 0x4C560

257
src/saturn/game.c Normal file
View File

@ -0,0 +1,257 @@
#include "inc_asm.h"
INCLUDE_ASM("asm/saturn/game", d6066000, d_06066000);
INCLUDE_ASM("asm/saturn/game", f6066040, func_06066040);
INCLUDE_ASM("asm/saturn/game", f60661BC, func_060661BC);
INCLUDE_ASM("asm/saturn/game", f6066330, func_06066330);
INCLUDE_ASM("asm/saturn/game", f6066400, func_06066400);
INCLUDE_ASM("asm/saturn/game", f60664E0, func_060664E0);
INCLUDE_ASM("asm/saturn/game", f60665BC, func_060665BC);
INCLUDE_ASM("asm/saturn/game", f60666A4, func_060666A4);
INCLUDE_ASM("asm/saturn/game", f6066854, func_06066854);
INCLUDE_ASM("asm/saturn/game", f60668D4, func_060668D4);
INCLUDE_ASM("asm/saturn/game", f6066B30, func_06066B30);
INCLUDE_ASM("asm/saturn/game", f6066B74, func_06066B74);
INCLUDE_ASM("asm/saturn/game", f6066CE0, func_06066CE0);
INCLUDE_ASM("asm/saturn/game", f6066FE0, func_06066FE0);
INCLUDE_ASM("asm/saturn/game", f6067090, func_06067090);
INCLUDE_ASM("asm/saturn/game", f60674B8, func_060674B8);
INCLUDE_ASM("asm/saturn/game", f6067958, func_06067958);
INCLUDE_ASM("asm/saturn/game", d606797C, d_0606797C);
INCLUDE_ASM("asm/saturn/game", f6067A04, func_06067A04);
INCLUDE_ASM("asm/saturn/game", f606B6F8, func_0606B6F8);
INCLUDE_ASM("asm/saturn/game", f606B760, func_0606B760);
INCLUDE_ASM("asm/saturn/game", f606BB4C, func_0606BB4C);
INCLUDE_ASM("asm/saturn/game", f606BEE4, func_0606BEE4);
INCLUDE_ASM("asm/saturn/game", f606C064, func_0606C064);
INCLUDE_ASM("asm/saturn/game", f606C088, func_0606C088);
INCLUDE_ASM("asm/saturn/game", f606C160, func_0606C160);
INCLUDE_ASM("asm/saturn/game", f606C3E4, func_0606C3E4);
INCLUDE_ASM("asm/saturn/game", f606C504, func_0606C504);
INCLUDE_ASM("asm/saturn/game", f606C594, func_0606C594);
INCLUDE_ASM("asm/saturn/game", f606C774, func_0606C774);
INCLUDE_ASM("asm/saturn/game", f606CA10, func_0606CA10);
INCLUDE_ASM("asm/saturn/game", f606D058, func_0606D058);
INCLUDE_ASM("asm/saturn/game", f606D2D0, func_0606D2D0);
INCLUDE_ASM("asm/saturn/game", f606D358, func_0606D358);
INCLUDE_ASM("asm/saturn/game", f606D3FC, func_0606D3FC);
INCLUDE_ASM("asm/saturn/game", f606D554, func_0606D554);
INCLUDE_ASM("asm/saturn/game", f606D5FC, func_0606D5FC);
INCLUDE_ASM("asm/saturn/game", f606D6DC, func_0606D6DC);
INCLUDE_ASM("asm/saturn/game", f606D798, func_0606D798);
INCLUDE_ASM("asm/saturn/game", f606D804, func_0606D804);
INCLUDE_ASM("asm/saturn/game", f606D880, func_0606D880);
INCLUDE_ASM("asm/saturn/game", f606DAE8, func_0606DAE8);
INCLUDE_ASM("asm/saturn/game", f606DC8C, func_0606DC8C);
INCLUDE_ASM("asm/saturn/game", f606DCF0, func_0606DCF0);
INCLUDE_ASM("asm/saturn/game", f606DF2C, func_0606DF2C);
INCLUDE_ASM("asm/saturn/game", f606DFA0, func_0606DFA0);
INCLUDE_ASM("asm/saturn/game", f606E020, func_0606E020);
INCLUDE_ASM("asm/saturn/game", f606E074, func_0606E074);
INCLUDE_ASM("asm/saturn/game", f606E0D0, func_0606E0D0);
INCLUDE_ASM("asm/saturn/game", f606EE28, func_0606EE28);
INCLUDE_ASM("asm/saturn/game", f606EEF8, func_0606EEF8);
INCLUDE_ASM("asm/saturn/game", f606F01C, func_0606F01C);
INCLUDE_ASM("asm/saturn/game", f606F14C, func_0606F14C);
INCLUDE_ASM("asm/saturn/game", f606F1C8, func_0606F1C8);
INCLUDE_ASM("asm/saturn/game", f606F21C, func_0606F21C);
INCLUDE_ASM("asm/saturn/game", f606F2C0, func_0606F2C0);
INCLUDE_ASM("asm/saturn/game", f606F328, func_0606F328);
INCLUDE_ASM("asm/saturn/game", f606F348, func_0606F348);
INCLUDE_ASM("asm/saturn/game", f606F378, func_0606F378);
INCLUDE_ASM("asm/saturn/game", f606F3D8, func_0606F3D8);
INCLUDE_ASM("asm/saturn/game", f606F3F8, func_0606F3F8);
INCLUDE_ASM("asm/saturn/game", f606F418, func_0606F418);
INCLUDE_ASM("asm/saturn/game", f606F448, func_0606F448);
INCLUDE_ASM("asm/saturn/game", f606F4C4, func_0606F4C4);
INCLUDE_ASM("asm/saturn/game", f606F59C, func_0606F59C);
INCLUDE_ASM("asm/saturn/game", f606F65C, func_0606F65C);
INCLUDE_ASM("asm/saturn/game", f606F760, func_0606F760);
INCLUDE_ASM("asm/saturn/game", f606F798, func_0606F798);
INCLUDE_ASM("asm/saturn/game", f606F800, func_0606F800);
INCLUDE_ASM("asm/saturn/game", f606F884, func_0606F884);
INCLUDE_ASM("asm/saturn/game", f606F8A8, func_0606F8A8);
INCLUDE_ASM("asm/saturn/game", f606FA30, func_0606FA30);
INCLUDE_ASM("asm/saturn/game", f606FC60, func_0606FC60);
INCLUDE_ASM("asm/saturn/game", f606FC80, func_0606FC80);
INCLUDE_ASM("asm/saturn/game", f606FE60, func_0606FE60);
INCLUDE_ASM("asm/saturn/game", f606FFA0, func_0606FFA0);
INCLUDE_ASM("asm/saturn/game", f606FFC8, func_0606FFC8);
INCLUDE_ASM("asm/saturn/game", f606FFE4, func_0606FFE4);
INCLUDE_ASM("asm/saturn/game", f607003C, func_0607003C);
INCLUDE_ASM("asm/saturn/game", f60703DC, func_060703DC);
INCLUDE_ASM("asm/saturn/game", f6070410, func_06070410);
INCLUDE_ASM("asm/saturn/game", f6070540, func_06070540);
INCLUDE_ASM("asm/saturn/game", f6070568, func_06070568);
INCLUDE_ASM("asm/saturn/game", f6070580, func_06070580);
INCLUDE_ASM("asm/saturn/game", f60705A0, func_060705A0);
INCLUDE_ASM("asm/saturn/game", f60705B8, func_060705B8);
INCLUDE_ASM("asm/saturn/game", f60705CC, func_060705CC);
INCLUDE_ASM("asm/saturn/game", f60707F0, func_060707F0);
INCLUDE_ASM("asm/saturn/game", f6070820, func_06070820);
INCLUDE_ASM("asm/saturn/game", f6070938, func_06070938);
INCLUDE_ASM("asm/saturn/game", f6070988, func_06070988);
INCLUDE_ASM("asm/saturn/game", d6070A60, d_06070A60);
INCLUDE_ASM("asm/saturn/game", f6071C3C, func_06071C3C);
INCLUDE_ASM("asm/saturn/game", f60720F4, func_060720F4);
INCLUDE_ASM("asm/saturn/game", f60726A8, func_060726A8);
INCLUDE_ASM("asm/saturn/game", f60727DC, func_060727DC);
INCLUDE_ASM("asm/saturn/game", f607284C, func_0607284C);
INCLUDE_ASM("asm/saturn/game", d60728B4, d_060728B4);
INCLUDE_ASM("asm/saturn/game", f6072BCC, func_06072BCC);
INCLUDE_ASM("asm/saturn/game", f6072C04, func_06072C04);
INCLUDE_ASM("asm/saturn/game", f6072C94, func_06072C94);
INCLUDE_ASM("asm/saturn/game", f60731C0, func_060731C0);
INCLUDE_ASM("asm/saturn/game", f6073280, func_06073280);
INCLUDE_ASM("asm/saturn/game", f60732E4, func_060732E4);
INCLUDE_ASM("asm/saturn/game", f60733A4, func_060733A4);
INCLUDE_ASM("asm/saturn/game", f607356C, func_0607356C);
INCLUDE_ASM("asm/saturn/game", f60735A4, func_060735A4);
INCLUDE_ASM("asm/saturn/game", f607360C, func_0607360C);
INCLUDE_ASM("asm/saturn/game", f607369C, func_0607369C);
INCLUDE_ASM("asm/saturn/game", f60736D4, func_060736D4);
INCLUDE_ASM("asm/saturn/game", f607371C, func_0607371C);
INCLUDE_ASM("asm/saturn/game", f6073740, func_06073740);
INCLUDE_ASM("asm/saturn/game", f6073770, func_06073770);
INCLUDE_ASM("asm/saturn/game", f60737A0, func_060737A0);
INCLUDE_ASM("asm/saturn/game", f6073E58, func_06073E58);
INCLUDE_ASM("asm/saturn/game", f6073EEC, func_06073EEC);
INCLUDE_ASM("asm/saturn/game", f6073FEC, func_06073FEC);
INCLUDE_ASM("asm/saturn/game", f6074048, func_06074048);
INCLUDE_ASM("asm/saturn/game", f6074068, func_06074068);
INCLUDE_ASM("asm/saturn/game", f60740F8, func_060740F8);
INCLUDE_ASM("asm/saturn/game", f6074278, func_06074278);
INCLUDE_ASM("asm/saturn/game", f60743B8, func_060743B8);
INCLUDE_ASM("asm/saturn/game", f6074470, func_06074470);
INCLUDE_ASM("asm/saturn/game", f60744F8, func_060744F8);
INCLUDE_ASM("asm/saturn/game", f60745A0, func_060745A0);
INCLUDE_ASM("asm/saturn/game", f6074698, func_06074698);
INCLUDE_ASM("asm/saturn/game", f6074700, func_06074700);
INCLUDE_ASM("asm/saturn/game", f6074724, func_06074724);
INCLUDE_ASM("asm/saturn/game", f6074964, func_06074964);
INCLUDE_ASM("asm/saturn/game", f60749F8, func_060749F8);
INCLUDE_ASM("asm/saturn/game", f6074A98, func_06074A98);
INCLUDE_ASM("asm/saturn/game", f6074AA8, func_06074AA8);
INCLUDE_ASM("asm/saturn/game", f6074BF4, func_06074BF4);
INCLUDE_ASM("asm/saturn/game", f6074C28, func_06074C28);
INCLUDE_ASM("asm/saturn/game", f6074CC8, func_06074CC8);
INCLUDE_ASM("asm/saturn/game", f6075838, func_06075838);
INCLUDE_ASM("asm/saturn/game", f6075D24, func_06075D24);
INCLUDE_ASM("asm/saturn/game", f60766DC, func_060766DC);
INCLUDE_ASM("asm/saturn/game", f6076718, func_06076718);
INCLUDE_ASM("asm/saturn/game", f607672C, func_0607672C);
INCLUDE_ASM("asm/saturn/game", f6076A04, func_06076A04);
INCLUDE_ASM("asm/saturn/game", f6077148, func_06077148);
INCLUDE_ASM("asm/saturn/game", f607718C, func_0607718C);
INCLUDE_ASM("asm/saturn/game", f60771B0, func_060771B0);
INCLUDE_ASM("asm/saturn/game", f60771D4, func_060771D4);
INCLUDE_ASM("asm/saturn/game", f6077260, func_06077260);
INCLUDE_ASM("asm/saturn/game", f6077354, func_06077354);
INCLUDE_ASM("asm/saturn/game", f6077764, func_06077764);
INCLUDE_ASM("asm/saturn/game", f6077B20, func_06077B20);
INCLUDE_ASM("asm/saturn/game", f6077D88, func_06077D88);
INCLUDE_ASM("asm/saturn/game", f6078120, func_06078120);
INCLUDE_ASM("asm/saturn/game", f60784A8, func_060784A8);
INCLUDE_ASM("asm/saturn/game", f60784B8, func_060784B8);
INCLUDE_ASM("asm/saturn/game", f6078550, func_06078550);
INCLUDE_ASM("asm/saturn/game", f6078604, func_06078604);
INCLUDE_ASM("asm/saturn/game", f6078684, func_06078684);
INCLUDE_ASM("asm/saturn/game", f607872C, func_0607872C);
INCLUDE_ASM("asm/saturn/game", f6078748, func_06078748);
INCLUDE_ASM("asm/saturn/game", f60787C8, func_060787C8);
INCLUDE_ASM("asm/saturn/game", f6078920, func_06078920);
INCLUDE_ASM("asm/saturn/game", f60789C4, func_060789C4);
INCLUDE_ASM("asm/saturn/game", f6078D58, func_06078D58);
INCLUDE_ASM("asm/saturn/game", f6078E80, func_06078E80);
INCLUDE_ASM("asm/saturn/game", f6078F58, func_06078F58);
INCLUDE_ASM("asm/saturn/game", f6079008, func_06079008);
INCLUDE_ASM("asm/saturn/game", f60790B4, func_060790B4);
INCLUDE_ASM("asm/saturn/game", f6079208, func_06079208);
INCLUDE_ASM("asm/saturn/game", f60792B8, func_060792B8);
INCLUDE_ASM("asm/saturn/game", f6079424, func_06079424);
INCLUDE_ASM("asm/saturn/game", f6079580, func_06079580);
INCLUDE_ASM("asm/saturn/game", f6079670, func_06079670);
INCLUDE_ASM("asm/saturn/game", f607973C, func_0607973C);
INCLUDE_ASM("asm/saturn/game", f60797FC, func_060797FC);
INCLUDE_ASM("asm/saturn/game", f6079958, func_06079958);
INCLUDE_ASM("asm/saturn/game", f6079A2C, func_06079A2C);
INCLUDE_ASM("asm/saturn/game", f6079AF0, func_06079AF0);
INCLUDE_ASM("asm/saturn/game", f6079B74, func_06079B74);
INCLUDE_ASM("asm/saturn/game", f6079B9C, func_06079B9C);
INCLUDE_ASM("asm/saturn/game", f6079BB4, func_06079BB4);
INCLUDE_ASM("asm/saturn/game", f6079BCC, func_06079BCC);
INCLUDE_ASM("asm/saturn/game", f6079BE4, func_06079BE4);
INCLUDE_ASM("asm/saturn/game", f6079C04, func_06079C04);
INCLUDE_ASM("asm/saturn/game", f6079DEC, func_06079DEC);
INCLUDE_ASM("asm/saturn/game", f6079F60, func_06079F60);
INCLUDE_ASM("asm/saturn/game", f607A030, func_0607A030);
INCLUDE_ASM("asm/saturn/game", f607A118, func_0607A118);
INCLUDE_ASM("asm/saturn/game", f607A1C8, func_0607A1C8);
INCLUDE_ASM("asm/saturn/game", f607A290, func_0607A290);
INCLUDE_ASM("asm/saturn/game", f607A608, func_0607A608);
INCLUDE_ASM("asm/saturn/game", f607A88C, func_0607A88C);
INCLUDE_ASM("asm/saturn/game", f607A994, func_0607A994);
INCLUDE_ASM("asm/saturn/game", f607A9F8, func_0607A9F8);
INCLUDE_ASM("asm/saturn/game", f607AA1C, func_0607AA1C);
INCLUDE_ASM("asm/saturn/game", f607AA40, func_0607AA40);
INCLUDE_ASM("asm/saturn/game", f607AA74, func_0607AA74);
INCLUDE_ASM("asm/saturn/game", f607AAA4, func_0607AAA4);
INCLUDE_ASM("asm/saturn/game", f607AACC, func_0607AACC);
INCLUDE_ASM("asm/saturn/game", f607AAF4, func_0607AAF4);
INCLUDE_ASM("asm/saturn/game", f607AB1C, func_0607AB1C);
INCLUDE_ASM("asm/saturn/game", f607AB4C, func_0607AB4C);
INCLUDE_ASM("asm/saturn/game", f607AB84, func_0607AB84);
INCLUDE_ASM("asm/saturn/game", f607ABBC, func_0607ABBC);
INCLUDE_ASM("asm/saturn/game", f607ABF4, func_0607ABF4);
INCLUDE_ASM("asm/saturn/game", f607AC2C, func_0607AC2C);
INCLUDE_ASM("asm/saturn/game", f607AC40, func_0607AC40);
INCLUDE_ASM("asm/saturn/game", f607AE48, func_0607AE48);
INCLUDE_ASM("asm/saturn/game", f607AECC, func_0607AECC);
INCLUDE_ASM("asm/saturn/game", f607AF0C, func_0607AF0C);
INCLUDE_ASM("asm/saturn/game", f607AF28, func_0607AF28);
INCLUDE_ASM("asm/saturn/game", f607AF3C, func_0607AF3C);
INCLUDE_ASM("asm/saturn/game", f607AF68, func_0607AF68);
INCLUDE_ASM("asm/saturn/game", f607AF94, func_0607AF94);
INCLUDE_ASM("asm/saturn/game", f607AFD8, func_0607AFD8);
INCLUDE_ASM("asm/saturn/game", f607B014, func_0607B014);
INCLUDE_ASM("asm/saturn/game", f607B04C, func_0607B04C);
INCLUDE_ASM("asm/saturn/game", f607B0AC, func_0607B0AC);
INCLUDE_ASM("asm/saturn/game", f607B0D0, func_0607B0D0);
INCLUDE_ASM("asm/saturn/game", f607B104, func_0607B104);
INCLUDE_ASM("asm/saturn/game", f607B134, func_0607B134);
INCLUDE_ASM("asm/saturn/game", f607B184, func_0607B184);
INCLUDE_ASM("asm/saturn/game", f607B1C8, func_0607B1C8);
INCLUDE_ASM("asm/saturn/game", f607B218, func_0607B218);
INCLUDE_ASM("asm/saturn/game", f607B240, func_0607B240);
INCLUDE_ASM("asm/saturn/game", f607B264, func_0607B264);
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
extern u32 g_randomNext;
// SAT: func_0607B2F4
s32 Random(void) {
g_randomNext = (g_randomNext * 0x01010101) + 1;
return g_randomNext >> 0x18;
}
INCLUDE_ASM("asm/saturn/game", f607B318, func_0607B318);
INCLUDE_ASM("asm/saturn/game", f607B374, func_0607B374);
INCLUDE_ASM("asm/saturn/game", f607B3D0, func_0607B3D0);
INCLUDE_ASM("asm/saturn/game", f607B448, func_0607B448);
INCLUDE_ASM("asm/saturn/game", f607B4B8, func_0607B4B8);
INCLUDE_ASM("asm/saturn/game", f607B604, func_0607B604);
INCLUDE_ASM("asm/saturn/game", f607B618, func_0607B618);
INCLUDE_ASM("asm/saturn/game", f607B674, func_0607B674);
INCLUDE_ASM("asm/saturn/game", f607B714, func_0607B714);
INCLUDE_ASM("asm/saturn/game", f607B7B4, func_0607B7B4);
INCLUDE_ASM("asm/saturn/game", f607BE38, func_0607BE38);
INCLUDE_ASM("asm/saturn/game", f607BED0, func_0607BED0);
INCLUDE_ASM("asm/saturn/game", f607C054, func_0607C054);
INCLUDE_ASM("asm/saturn/game", f607C0A0, func_0607C0A0);
INCLUDE_ASM("asm/saturn/game", f607C0BC, func_0607C0BC);

26
src/saturn/inc_asm.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef INCLUDE_ASM_H
#define INCLUDE_ASM_H
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef PERMUTER
#ifndef INCLUDE_ASM
#define INCLUDE_ASM(FOLDER, NAME, LABEL) \
__asm__(".text\n" \
"\t.align\t2\n" \
"\t.global\t _" #LABEL "\n" \
".include \"" FOLDER "/" #NAME ".s\"\n");
#endif
// omit .global
__asm__(".include \"macro.inc\"\n");
#else
#define INCLUDE_ASM(FOLDER, NAME)
#endif
#endif

4
src/saturn/macro.inc Normal file
View File

@ -0,0 +1,4 @@
.macro glabel label
.global \label
_\label:
.endm

112
src/saturn/t_bat.c Normal file
View File

@ -0,0 +1,112 @@
#include "inc_asm.h"
typedef signed char s8;
typedef signed short s16;
typedef signed int s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
// entity layout is different somehow
typedef struct Entity {
s16 temp;
s16 pad1;
s16 posx;
s16 pad3;
s16 posy;
s8 pad[0x25];
u16 subId;
} Entity;
INCLUDE_ASM("asm/saturn/t_bat", d60CF000, d_060CF000);
INCLUDE_ASM("asm/saturn/t_bat", f60CF060, func_060CF060);
INCLUDE_ASM("asm/saturn/t_bat", f60CF294, func_060CF294);
INCLUDE_ASM("asm/saturn/t_bat", f60CF2E8, func_060CF2E8);
INCLUDE_ASM("asm/saturn/t_bat", f60CF410, func_060CF410);
INCLUDE_ASM("asm/saturn/t_bat", f60CF5F4, func_060CF5F4);
INCLUDE_ASM("asm/saturn/t_bat", f60CF6B4, func_060CF6B4);
INCLUDE_ASM("asm/saturn/t_bat", f60CFB00, func_060CFB00);
INCLUDE_ASM("asm/saturn/t_bat", f60CFC48, func_060CFC48);
INCLUDE_ASM("asm/saturn/t_bat", f60D0490, func_060D0490);
void f60D0938() {}
void f60D0944() {}
void f60D0950() {}
void f60D095C() {}
INCLUDE_ASM("asm/saturn/t_bat", f60D0968, func_060D0968);
void f60D0A4C() {}
void f60D0A58() {}
INCLUDE_ASM("asm/saturn/t_bat", f60D0A64, func_060D0A64);
void f60D1010() {}
void f60D101C() {}
void f60D1028() {}
void f60D1034() {}
extern s32 D_80174D3C; // 0x060D1DFCh
void DestroyEntity(Entity*); // func_0600FFB8h
// PSX: func_80173C2C
// SAT: func_060D1040
void func_80173C2C(Entity* entity) {
if (entity->subId == 0xF) {
D_80174D3C = 1;
}
func_0600FFB8(entity); // DestroyEntity
}
INCLUDE_ASM("asm/saturn/t_bat", f60D1070, func_060D1070);
// PSX: TT_000:func_80173E78
// SAT: T_BAT:f_021B8 / func_060D11B8
s32 func_80173E78(s32 arg0, s32 arg1) {
if (arg0 < 0) {
arg0 += arg1;
if (arg0 > 0) {
arg0 = 0;
}
} else {
arg0 -= arg1;
if (arg0 < 0) {
arg0 = 0;
}
}
return arg0;
}
INCLUDE_ASM("asm/saturn/t_bat", f60D11DC, func_060D11DC);
// PSX: func_80173F30
// SAT: func_060D1224
s32 func_80173F30(Entity* entity, s16 x, s16 y) {
s16 diffx = x - entity->posx; // was entity->posX.i.hi
// not the same implementation as ratan2
return func_0600EE88(-(s16)(y - entity->posy), diffx) &
0xFFF; // was entity->posY.i.hi
}
INCLUDE_ASM("asm/saturn/t_bat", f60D125C, func_060D125C);
s32 func_0600F914(s32, s32);
// SAT: func_060D12AC
// PSX: func_80173FE8
s32 func_80173FE8(Entity* entity, s32 x, s32 y) {
s32 diffX = x - entity->posx;
s32 diffY = y - entity->posy;
// not shifted by 12
return func_0600F914((diffX * diffX + diffY * diffY),
diffX); // SquareRoot12
}
INCLUDE_ASM("asm/saturn/t_bat", f60D12DC, func_060D12DC);
INCLUDE_ASM("asm/saturn/t_bat", f60D141C, func_060D141C);
INCLUDE_ASM("asm/saturn/t_bat", f60D1640, func_060D1640);
INCLUDE_ASM("asm/saturn/t_bat", f60D16D0, func_060D16D0);
INCLUDE_ASM("asm/saturn/t_bat", f60D1784, func_060D1784);
INCLUDE_ASM("asm/saturn/t_bat", f60D1808, func_060D1808);
INCLUDE_ASM("asm/saturn/t_bat", d60D1858, d_060D1858);

8
src/saturn/zero.c Normal file
View File

@ -0,0 +1,8 @@
#include "inc_asm.h"
INCLUDE_ASM("asm/saturn/zero", d6004080, d_06004080);
INCLUDE_ASM("asm/saturn/zero", f600EE88, func_0600EE88);
INCLUDE_ASM("asm/saturn/zero", d600EFBC, d_0600EFBC);
INCLUDE_ASM("asm/saturn/zero", f600F914, func_0600F914);
INCLUDE_ASM("asm/saturn/zero", d600F96C, d_0600F96C);
INCLUDE_ASM("asm/saturn/zero", f600FFB8, func_0600FFB8);
INCLUDE_ASM("asm/saturn/zero", d6010008, d_06010008);

@ -1 +1 @@
Subproject commit 25606b6fbd65c49e59a86524db873de705d4b755 Subproject commit b97e6ad562501326ef0a3542950a9aea31da4fa4

View File

@ -0,0 +1,4 @@
FROM debian:bookworm
RUN apt-get update && \
apt-get install binutils-sh-elf -y

View File

@ -0,0 +1,2 @@
# build object file with dosemu
HOME="." dosemu -quiet -dumb -f ./dosemurc -K . -E "GCC.EXE -c -O2 -m2 -fsigned-char $FILENAME.c -o $FILENAME.o"

6
tools/saturn_toolchain/diff.sh Executable file
View File

@ -0,0 +1,6 @@
# disassemble our binary
sh-elf-objdump -z -m sh2 -b binary -D $FILENAME > $FILENAME-ours.txt &&
# disassemble their binary
sh-elf-objdump -z -m sh2 -b binary -D /theirs/$FILENAME > $FILENAME-theirs.txt &&
# diff
diff $FILENAME-ours.txt $FILENAME-theirs.txt > $FILENAME-diff.txt || true

View File

@ -0,0 +1,30 @@
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y -o APT::Immediate-Configure=false \
dos2unix software-properties-common && \
add-apt-repository -y ppa:dosemu2/ppa && \
apt-get update && \
apt-get install -y dosemu2;
ARG USERNAME=user
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
#
# [Optional] Add sudo support. Omit if you don't need to install software after connecting.
&& apt-get update \
&& apt-get install -y sudo \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
RUN mkdir -p /etc/dosemu/drives/c && chmod -R 777 /etc/dosemu/drives/c
RUN chmod -R 777 /etc/dosemu/drives/c
USER $USERNAME
WORKDIR /etc/dosemu/drives/c

View File

@ -0,0 +1,2 @@
# strip our binary
sh-elf-objcopy /build/$INPUT_FILENAME -O binary /build/$OUTPUT_FILENAME