Initial commit

This commit is contained in:
Luke Street 2022-03-23 17:22:48 -04:00
commit ce247fb264
32 changed files with 1133268 additions and 0 deletions

10
.gitattributes vendored Normal file
View File

@ -0,0 +1,10 @@
# Auto detect text files and perform LF normalization
* text=auto
# Explicitly declare text files
*.py text
# Enforce platform-specific encodings
*.bat text eol=crlf
*.sh text eol=lf
*.sha1 text eol=lf

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
.vscode
*.dat
*.exe
*.dll
*.idb
*.id0
*.id1
*.id2
*.nam
*.til
*.o
*.out
*.elf
*.dol
*.a
*.d
*.map
*.exe
*.dump
*.7z
*.bat
*.sln
*.filters
*.vcxproj
*.user
include/*.s
build/
tools/mwcc_compiler/
tools/elf2dol
tools/elf2rel
decomp/
errors.txt
output.asm
Debug/
.vs/
ctx.c

208
Makefile Normal file
View File

@ -0,0 +1,208 @@
ifneq ($(findstring MINGW,$(shell uname)),)
WINDOWS := 1
endif
ifneq ($(findstring MSYS,$(shell uname)),)
WINDOWS := 1
endif
# If 0, tells the console to chill out. (Quiets the make process.)
VERBOSE ?= 1
# If MAPGENFLAG set to 1, tells LDFLAGS to generate a mapfile, which makes linking take several minutes.
MAPGENFLAG ?= 1
ifeq ($(VERBOSE),0)
QUIET := @
endif
#-------------------------------------------------------------------------------
# Files
#-------------------------------------------------------------------------------
NAME := mp1
VERSION ?= 0
# Overkill epilogue fixup strategy. Set to 1 if necessary.
EPILOGUE_PROCESS := 0
BUILD_DIR := build/$(NAME).$(VERSION)
ifeq ($(EPILOGUE_PROCESS),1)
EPILOGUE_DIR := epilogue/$(NAME).$(VERSION)
endif
# Inputs
S_FILES := $(wildcard asm/*.s)
C_FILES := $(wildcard src/*.c)
CPP_FILES := $(wildcard src/*.cpp)
CPP_FILES += $(wildcard src/*.cp)
LDSCRIPT := $(BUILD_DIR)/ldscript.lcf
# Outputs
DOL := $(BUILD_DIR)/main.dol
ELF := $(DOL:.dol=.elf)
MAP := $(BUILD_DIR)/MetroidPrime.MAP
ifeq ($(MAPGENFLAG),1)
MAPGEN := -map $(MAP)
endif
include obj_files.mk
ifeq ($(EPILOGUE_PROCESS),1)
include e_files.mk
endif
O_FILES := $(INIT_O_FILES) $(EXTAB_O_FILES) $(EXTABINDEX_O_FILES) $(TEXT_O_FILES) \
$(CTORS_O_FILES) $(DTORS_O_FILES) $(RODATA_O_FILES) $(DATA_O_FILES) \
$(BSS_O_FILES) $(SDATA_O_FILES) $(SBSS_O_FILES) $(SDATA2_O_FILES) \
$(SBSS2_O_FILES)
ifeq ($(EPILOGUE_PROCESS),1)
E_FILES := $(EPILOGUE_UNSCHEDULED)
endif
#-------------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------------
MWCC_VERSION := 2.6
ifeq ($(EPILOGUE_PROCESS),1)
MWCC_EPI_VERSION := 1.2.5
MWCC_EPI_EXE := mwcceppc.exe
endif
MWLD_VERSION := 2.6
# Programs
ifeq ($(WINDOWS),1)
WINE :=
AS := $(DEVKITPPC)/bin/powerpc-eabi-as.exe
CPP := $(DEVKITPPC)/bin/powerpc-eabi-cpp.exe -P
else
WINE ?= wine
AS := $(DEVKITPPC)/bin/powerpc-eabi-as
CPP := $(DEVKITPPC)/bin/powerpc-eabi-cpp -P
endif
CC = $(WINE) tools/mwcc_compiler/$(MWCC_VERSION)/mwcceppc.exe
ifeq ($(EPILOGUE_PROCESS),1)
CC_EPI = $(WINE) tools/mwcc_compiler/$(MWCC_EPI_VERSION)/$(MWCC_EPI_EXE)
endif
LD := $(WINE) tools/mwcc_compiler/$(MWLD_VERSION)/mwldeppc.exe
ELF2DOL := tools/elf2dol
SHA1SUM := sha1sum
PYTHON := python3
FRANK := tools/franklite.py
# Options
INCLUDES := -i include/
ASM_INCLUDES := -I include/
ASFLAGS := -mgekko $(ASM_INCLUDES) --defsym version=$(VERSION)
ifeq ($(VERBOSE),1)
# this set of LDFLAGS outputs warnings.
LDFLAGS := $(MAPGEN) -fp hard -nodefaults
endif
ifeq ($(VERBOSE),0)
# this set of LDFLAGS generates no warnings.
LDFLAGS := $(MAPGEN) -fp hard -nodefaults -w off
endif
CFLAGS = -Cpp_exceptions off -enum int -inline auto -proc gekko -RTTI off -fp hard -fp_contract on -rostr -O4,p -use_lmw_stmw on -sdata 8 -sdata2 8 -nodefaults $(INCLUDES)
ifeq ($(VERBOSE),0)
# this set of ASFLAGS generates no warnings.
ASFLAGS += -W
endif
$(BUILD_DIR)/src/os/__start.o: MWCC_VERSION := 1.2.5
#-------------------------------------------------------------------------------
# Recipes
#-------------------------------------------------------------------------------
### Default target ###
default: all
all: $(DOL)
ALL_DIRS := $(sort $(dir $(O_FILES)))
ifeq ($(EPILOGUE_PROCESS),1)
EPI_DIRS := $(sort $(dir $(E_FILES)))
endif
# Make sure build directory exists before compiling anything
DUMMY != mkdir -p $(ALL_DIRS)
# ifeq ($(EPILOGUE_PROCESS),1)
# Make sure profile directory exists before compiling anything
# DUMMY != mkdir -p $(EPI_DIRS)
# endif
.PHONY: tools
$(LDSCRIPT): ldscript.lcf
$(QUIET) $(CPP) -MMD -MP -MT $@ -MF $@.d -I include/ -I . -DBUILD_DIR=$(BUILD_DIR) -o $@ $<
$(DOL): $(ELF) | tools
$(QUIET) $(ELF2DOL) $< $@
$(QUIET) $(SHA1SUM) -c sha1/$(NAME).$(VERSION).sha1
ifneq ($(findstring -map,$(LDFLAGS)),)
$(QUIET) $(PYTHON) tools/calcprogress.py $@
endif
clean:
rm -f -d -r build
rm -f -d -r epilogue
find . -name '*.o' -exec rm {} +
find . -name 'ctx.c' -exec rm {} +
find ./include -name "*.s" -type f -delete
$(MAKE) -C tools clean
tools:
$(MAKE) -C tools
# ELF creation makefile instructions
ifeq ($(EPILOGUE_PROCESS),1)
@echo Linking ELF $@
$(ELF): $(O_FILES) $(E_FILES) $(LDSCRIPT)
$(QUIET) @echo $(O_FILES) > build/o_files
$(QUIET) $(LD) $(LDFLAGS) -o $@ -lcf $(LDSCRIPT) @build/o_files
else
$(ELF): $(O_FILES) $(LDSCRIPT)
@echo Linking ELF $@
$(QUIET) @echo $(O_FILES) > build/o_files
$(QUIET) $(LD) $(LDFLAGS) -o $@ -lcf $(LDSCRIPT) @build/o_files
endif
$(BUILD_DIR)/%.o: %.s
@echo Assembling $<
$(QUIET) $(AS) $(ASFLAGS) -o $@ $<
$(BUILD_DIR)/%.o: %.c
@echo "Compiling " $<
$(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
$(BUILD_DIR)/%.o: %.cp
@echo "Compiling " $<
$(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
$(BUILD_DIR)/%.o: %.cpp
@echo "Compiling " $<
$(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
ifeq ($(EPILOGUE_PROCESS),1)
$(EPILOGUE_DIR)/%.o: %.c $(BUILD_DIR)/%.o
@echo Frank is fixing $<
$(QUIET) $(PYTHON) $(FRANK) $(word 2,$^) $(word 2,$^)
$(EPILOGUE_DIR)/%.o: %.cp $(BUILD_DIR)/%.o
@echo Frank is fixing $<
$(QUIET) $(PYTHON) $(FRANK) $(word 2,$^) $(word 2,$^)
$(EPILOGUE_DIR)/%.o: %.cpp $(BUILD_DIR)/%.o
@echo Frank is fixing $<
$(QUIET) $(PYTHON) $(FRANK) $(word 2,$^) $(word 2,$^)
endif
# If we need Frank, add the following after the @echo
# $(QUIET) $(CC_EPI) $(CFLAGS) -c -o $@ $<
### Debug Print ###
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true

View File

@ -0,0 +1,104 @@
.include "macros.inc"
.section .init, "ax" # 0x80003100 - 0x80005620
.global memset
memset:
/* 800033A8 000003A8 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 800033AC 000003AC 7C 08 02 A6 */ mflr r0
/* 800033B0 000003B0 90 01 00 14 */ stw r0, 0x14(r1)
/* 800033B4 000003B4 93 E1 00 0C */ stw r31, 0xc(r1)
/* 800033B8 000003B8 7C 7F 1B 78 */ mr r31, r3
/* 800033BC 000003BC 48 00 00 1D */ bl __fill_mem
/* 800033C0 000003C0 80 01 00 14 */ lwz r0, 0x14(r1)
/* 800033C4 000003C4 7F E3 FB 78 */ mr r3, r31
/* 800033C8 000003C8 83 E1 00 0C */ lwz r31, 0xc(r1)
/* 800033CC 000003CC 7C 08 03 A6 */ mtlr r0
/* 800033D0 000003D0 38 21 00 10 */ addi r1, r1, 0x10
/* 800033D4 000003D4 4E 80 00 20 */ blr
.global __fill_mem
__fill_mem:
/* 800033D8 000003D8 28 05 00 20 */ cmplwi r5, 0x20
/* 800033DC 000003DC 54 84 06 3E */ clrlwi r4, r4, 0x18
/* 800033E0 000003E0 38 C3 FF FF */ addi r6, r3, -1
/* 800033E4 000003E4 7C 87 23 78 */ mr r7, r4
/* 800033E8 000003E8 41 80 00 90 */ blt lbl_80003478
/* 800033EC 000003EC 7C C0 30 F8 */ nor r0, r6, r6
/* 800033F0 000003F0 54 03 07 BF */ clrlwi. r3, r0, 0x1e
/* 800033F4 000003F4 41 82 00 14 */ beq lbl_80003408
/* 800033F8 000003F8 7C A3 28 50 */ subf r5, r3, r5
lbl_800033FC:
/* 800033FC 000003FC 34 63 FF FF */ addic. r3, r3, -1
/* 80003400 00000400 9C E6 00 01 */ stbu r7, 1(r6)
/* 80003404 00000404 40 82 FF F8 */ bne lbl_800033FC
lbl_80003408:
/* 80003408 00000408 28 07 00 00 */ cmplwi r7, 0
/* 8000340C 0000040C 41 82 00 1C */ beq lbl_80003428
/* 80003410 00000410 54 E3 C0 0E */ slwi r3, r7, 0x18
/* 80003414 00000414 54 E0 80 1E */ slwi r0, r7, 0x10
/* 80003418 00000418 54 E4 40 2E */ slwi r4, r7, 8
/* 8000341C 0000041C 7C 60 03 78 */ or r0, r3, r0
/* 80003420 00000420 7C 80 03 78 */ or r0, r4, r0
/* 80003424 00000424 7C E7 03 78 */ or r7, r7, r0
lbl_80003428:
/* 80003428 00000428 54 A3 D9 7F */ rlwinm. r3, r5, 0x1b, 5, 0x1f
/* 8000342C 0000042C 38 86 FF FD */ addi r4, r6, -3
/* 80003430 00000430 41 82 00 2C */ beq lbl_8000345C
lbl_80003434:
/* 80003434 00000434 90 E4 00 04 */ stw r7, 4(r4)
/* 80003438 00000438 34 63 FF FF */ addic. r3, r3, -1
/* 8000343C 0000043C 90 E4 00 08 */ stw r7, 8(r4)
/* 80003440 00000440 90 E4 00 0C */ stw r7, 0xc(r4)
/* 80003444 00000444 90 E4 00 10 */ stw r7, 0x10(r4)
/* 80003448 00000448 90 E4 00 14 */ stw r7, 0x14(r4)
/* 8000344C 0000044C 90 E4 00 18 */ stw r7, 0x18(r4)
/* 80003450 00000450 90 E4 00 1C */ stw r7, 0x1c(r4)
/* 80003454 00000454 94 E4 00 20 */ stwu r7, 0x20(r4)
/* 80003458 00000458 40 82 FF DC */ bne lbl_80003434
lbl_8000345C:
/* 8000345C 0000045C 54 A3 F7 7F */ rlwinm. r3, r5, 0x1e, 0x1d, 0x1f
/* 80003460 00000460 41 82 00 10 */ beq lbl_80003470
lbl_80003464:
/* 80003464 00000464 34 63 FF FF */ addic. r3, r3, -1
/* 80003468 00000468 94 E4 00 04 */ stwu r7, 4(r4)
/* 8000346C 0000046C 40 82 FF F8 */ bne lbl_80003464
lbl_80003470:
/* 80003470 00000470 38 C4 00 03 */ addi r6, r4, 3
/* 80003474 00000474 54 A5 07 BE */ clrlwi r5, r5, 0x1e
lbl_80003478:
/* 80003478 00000478 28 05 00 00 */ cmplwi r5, 0
/* 8000347C 0000047C 4D 82 00 20 */ beqlr
lbl_80003480:
/* 80003480 00000480 34 A5 FF FF */ addic. r5, r5, -1
/* 80003484 00000484 9C E6 00 01 */ stbu r7, 1(r6)
/* 80003488 00000488 40 82 FF F8 */ bne lbl_80003480
/* 8000348C 0000048C 4E 80 00 20 */ blr
.global memcpy
memcpy:
/* 80003490 00000490 7C 04 18 40 */ cmplw r4, r3
/* 80003494 00000494 41 80 00 28 */ blt lbl_800034BC
/* 80003498 00000498 38 84 FF FF */ addi r4, r4, -1
/* 8000349C 0000049C 38 C3 FF FF */ addi r6, r3, -1
/* 800034A0 000004A0 38 A5 00 01 */ addi r5, r5, 1
/* 800034A4 000004A4 48 00 00 0C */ b lbl_800034B0
lbl_800034A8:
/* 800034A8 000004A8 8C 04 00 01 */ lbzu r0, 1(r4)
/* 800034AC 000004AC 9C 06 00 01 */ stbu r0, 1(r6)
lbl_800034B0:
/* 800034B0 000004B0 34 A5 FF FF */ addic. r5, r5, -1
/* 800034B4 000004B4 40 82 FF F4 */ bne lbl_800034A8
/* 800034B8 000004B8 4E 80 00 20 */ blr
lbl_800034BC:
/* 800034BC 000004BC 7C 84 2A 14 */ add r4, r4, r5
/* 800034C0 000004C0 7C C3 2A 14 */ add r6, r3, r5
/* 800034C4 000004C4 38 A5 00 01 */ addi r5, r5, 1
/* 800034C8 000004C8 48 00 00 0C */ b lbl_800034D4
lbl_800034CC:
/* 800034CC 000004CC 8C 04 FF FF */ lbzu r0, -1(r4)
/* 800034D0 000004D0 9C 06 FF FF */ stbu r0, -1(r6)
lbl_800034D4:
/* 800034D4 000004D4 34 A5 FF FF */ addic. r5, r5, -1
/* 800034D8 000004D8 40 82 FF F4 */ bne lbl_800034CC
/* 800034DC 000004DC 4E 80 00 20 */ blr

1143
asm/bss.s Normal file

File diff suppressed because it is too large Load Diff

6
asm/ctors.s Normal file
View File

@ -0,0 +1,6 @@
.include "macros.inc"
.section .ctors, "wa" # 0x803CB1C0 - 0x803CB380
.global lbl_803CB1C0
lbl_803CB1C0:
.incbin "baserom.dol", 0x3C81C0, 0x1C0

2925
asm/data.s Normal file

File diff suppressed because it is too large Load Diff

6
asm/dtors.s Normal file
View File

@ -0,0 +1,6 @@
.include "macros.inc"
.section .dtors, "wa" # 0x803CB380 - 0x803CB3A0
.global lbl_803CB380
lbl_803CB380:
.incbin "baserom.dol", 0x3C8380, 0x10

6
asm/extab.s Normal file
View File

@ -0,0 +1,6 @@
.include "macros.inc"
.section extab_, "wa" # 0x800035A0 - 0x800035E0
.global lbl_extab
lbl_extab:
.incbin "baserom.dol", 0x3C8120, 0x28

8
asm/extabindex.s Normal file
View File

@ -0,0 +1,8 @@
.include "macros.inc"
.section extabindex_, "wa" # 0x800035E0 - 0x80003640
lbl_extabindex:
.incbin "baserom.dol", 0x3C8160, 0x24
.global lbl_80003604
lbl_80003604:
.incbin "baserom.dol", 0x3C8184, 0x20

31
asm/os/__ppc_eabi_init.s Normal file
View File

@ -0,0 +1,31 @@
.include "macros.inc"
.section .init, "ax" # 0x80003100 - 0x80005620
.global __init_hardware
__init_hardware:
/* 80003354 00000354 7C 00 00 A6 */ mfmsr r0
/* 80003358 00000358 60 00 20 00 */ ori r0, r0, 0x2000
/* 8000335C 0000035C 7C 00 01 24 */ mtmsr r0
/* 80003360 00000360 7F E8 02 A6 */ mflr r31
/* 80003364 00000364 48 0B 19 49 */ bl __OSPSInit
/* 80003368 00000368 48 0B 32 8D */ bl __OSCacheInit
/* 8000336C 0000036C 7F E8 03 A6 */ mtlr r31
/* 80003370 00000370 4E 80 00 20 */ blr
.global __flush_cache
__flush_cache:
/* 80003374 00000374 3C A0 FF FF */ lis r5, 0xFFFFFFF1@h
/* 80003378 00000378 60 A5 FF F1 */ ori r5, r5, 0xFFFFFFF1@l
/* 8000337C 0000037C 7C A5 18 38 */ and r5, r5, r3
/* 80003380 00000380 7C 65 18 50 */ subf r3, r5, r3
/* 80003384 00000384 7C 84 1A 14 */ add r4, r4, r3
lbl_80003388:
/* 80003388 00000388 7C 00 28 6C */ dcbst 0, r5
/* 8000338C 0000038C 7C 00 04 AC */ sync 0
/* 80003390 00000390 7C 00 2F AC */ icbi 0, r5
/* 80003394 00000394 30 A5 00 08 */ addic r5, r5, 8
/* 80003398 00000398 34 84 FF F8 */ addic. r4, r4, -8
/* 8000339C 0000039C 40 80 FF EC */ bge lbl_80003388
/* 800033A0 000003A0 4C 00 01 2C */ isync
/* 800033A4 000003A4 4E 80 00 20 */ blr

1782
asm/rodata.s Normal file

File diff suppressed because it is too large Load Diff

2859
asm/sbss.s Normal file

File diff suppressed because it is too large Load Diff

69
asm/sbss2.s Normal file
View File

@ -0,0 +1,69 @@
.include "macros.inc"
.section .sbss2, "", @nobits # 0x805AF460 - 0x805AF4C7
.global lbl_805AF460
lbl_805AF460:
.skip 0x8
.global lbl_805AF468
lbl_805AF468:
.skip 0x4
.global lbl_805AF46C
lbl_805AF46C:
.skip 0x4
.global lbl_805AF470
lbl_805AF470:
.skip 0x4
.global lbl_805AF474
lbl_805AF474:
.skip 0x4
.global lbl_805AF478
lbl_805AF478:
.skip 0x4
.global lbl_805AF47C
lbl_805AF47C:
.skip 0x4
.global lbl_805AF480
lbl_805AF480:
.skip 0x8
.global lbl_805AF488
lbl_805AF488:
.skip 0x4
.global lbl_805AF48C
lbl_805AF48C:
.skip 0x4
.global lbl_805AF490
lbl_805AF490:
.skip 0x4
.global lbl_805AF494
lbl_805AF494:
.skip 0x4
.global lbl_805AF498
lbl_805AF498:
.skip 0x8
.global lbl_805AF4A0
lbl_805AF4A0:
.skip 0x8
.global lbl_805AF4A8
lbl_805AF4A8:
.skip 0x4
.global lbl_805AF4AC
lbl_805AF4AC:
.skip 0x4
.global lbl_805AF4B0
lbl_805AF4B0:
.skip 0x4
.global lbl_805AF4B4
lbl_805AF4B4:
.skip 0x4
.global lbl_805AF4B8
lbl_805AF4B8:
.skip 0x4
.global lbl_805AF4BC
lbl_805AF4BC:
.skip 0x4
.global lbl_805AF4C0
lbl_805AF4C0:
.skip 0x4
.global lbl_805AF4C4
lbl_805AF4C4:
.skip 0x4

5808
asm/sdata.s Normal file

File diff suppressed because it is too large Load Diff

14100
asm/sdata2.s Normal file

File diff suppressed because it is too large Load Diff

1101638
asm/text.s Normal file

File diff suppressed because it is too large Load Diff

7
asmdiff.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
OBJDUMP="$DEVKITPPC/bin/powerpc-eabi-objdump -D -bbinary -EB -mpowerpc -M gekko"
OPTIONS="--start-address=$(($1)) --stop-address=$(($1 + $2))"
$OBJDUMP $OPTIONS baserom.dol > baserom.dump
$OBJDUMP $OPTIONS build/mp1.0/main.dol > main.dump
diff -u --color=always baserom.dump main.dump

56
include/Dolphin/__start.h Normal file
View File

@ -0,0 +1,56 @@
#include "types.h"
#include "Dolphin/db.h"
#define PAD3_BUTTON_ADDR 0x800030E4
#define OS_RESET_RESTART 0
#define FALSE 0
#define TRUE 1
#define EXCEPTIONMASK_ADDR 0x80000044
#define BOOTINFO2_ADDR 0x800000F4
#define OS_BI2_DEBUGFLAG_OFFSET 0xC
#define ARENAHI_ADDR 0x80000034
#define DEBUGFLAG_ADDR 0x800030E8
#define DVD_DEVICECODE_ADDR 0x800030E6
#define MSR_FP 0x2000
extern void InitMetroTRK();
u16 Pad3Button : PAD3_BUTTON_ADDR;
static u8 Debug_BBA = 0;
extern void memset(void*,int,int);
extern int main(int argc, char* argv[]);
extern void exit(int);
extern void __init_user(void);
extern void OSInit(void);
extern void DBInit(void);
extern void OSResetSystem(BOOL reset, u32 resetCode, BOOL forceMenu);
extern void __OSCacheInit ( void );
extern void __OSPSInit ( void );
__declspec(section ".init") extern void __check_pad3(void);
__declspec(section ".init") extern void __start(void);
__declspec(section ".init") extern void __init_registers(void);
__declspec(section ".init") extern void __init_data(void);
__declspec(section ".init") extern void __init_hardware(void);
__declspec(section ".init") extern void __flush_cache(void *address, unsigned int size);
__declspec(section ".init") extern char _stack_addr[];
__declspec(section ".init") extern char _SDA_BASE_[];
__declspec(section ".init") extern char _SDA2_BASE_[];
typedef struct __rom_copy_info {
char* rom;
char* addr;
unsigned int size;
} __rom_copy_info;
__declspec(section ".init") extern __rom_copy_info _rom_copy_info[];
typedef struct __bss_init_info {
char* addr;
unsigned int size;
} __bss_init_info;
__declspec(section ".init") extern __bss_init_info _bss_init_info[];

23
include/Dolphin/db.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _DOLPHIN_DB_H
#define _DOLPHIN_DB_H
#include "types.h"
#define ExceptionHookDestination 0x80000048
#define IsDebuggerPresent 0x80000040
// static int __DBInterface;
struct DBInterface {
u8 filler0[4];
u32 unk4;
};
static struct DBInterface* __DBInterface;
static int DBVerbose;
void DBInit(void);
void DBInitComm(int* inputFlagPtr, int* mtrCallback);
static void __DBExceptionDestination(void);
#endif

92
include/macros.inc Normal file
View File

@ -0,0 +1,92 @@
/*
Code sections:
.init: 0x00000100 0x80003100 0x800035A0
.text: 0x000005A0 0x80003640 0x803CB1C0
Data sections:
extab_: 0x003C8120 0x800035A0 0x800035E0
extabindex_: 0x003C8160 0x800035E0 0x80003640
.ctors: 0x003C81C0 0x803CB1C0 0x803CB380
.dtors: 0x003C8380 0x803CB380 0x803CB3A0
.rodata: 0x003C83A0 0x803CB3A0 0x803D8D60
.data: 0x003D5D60 0x803D8D60 0x803F7560
.sdata: 0x003F4560 0x805A6BC0 0x805A8C20
.sbss:
.sdata2: 0x003F65C0 0x805A9D20 0x805AF460
.sbss2:
BSS section:
.bss: 0x00000000 0x803F7560 0x805A6BBF
Entry Point: 0x80003140
*/
# PowerPC Register Constants
.set r0, 0
.set r1, 1
.set r2, 2
.set r3, 3
.set r4, 4
.set r5, 5
.set r6, 6
.set r7, 7
.set r8, 8
.set r9, 9
.set r10, 10
.set r11, 11
.set r12, 12
.set r13, 13
.set r14, 14
.set r15, 15
.set r16, 16
.set r17, 17
.set r18, 18
.set r19, 19
.set r20, 20
.set r21, 21
.set r22, 22
.set r23, 23
.set r24, 24
.set r25, 25
.set r26, 26
.set r27, 27
.set r28, 28
.set r29, 29
.set r30, 30
.set r31, 31
.set f0, 0
.set f1, 1
.set f2, 2
.set f3, 3
.set f4, 4
.set f5, 5
.set f6, 6
.set f7, 7
.set f8, 8
.set f9, 9
.set f10, 10
.set f11, 11
.set f12, 12
.set f13, 13
.set f14, 14
.set f15, 15
.set f16, 16
.set f17, 17
.set f18, 18
.set f19, 19
.set f20, 20
.set f21, 21
.set f22, 22
.set f23, 23
.set f24, 24
.set f25, 25
.set f26, 26
.set f27, 27
.set f28, 28
.set f29, 29
.set f30, 30
.set f31, 31
.set qr0, 0
.set qr1, 1
.set qr2, 2
.set qr3, 3
.set qr4, 4
.set qr5, 5
.set qr6, 6
.set qr7, 7

71
include/types.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef _TYPES_H
#define _TYPES_H
//#include "BuildSettings.h"
// r2 is 801DC960
// r13 is 801DB420
typedef signed char s8;
typedef signed short s16;
typedef signed long s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long size_t;
typedef unsigned long long u64;
typedef unsigned int uint;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef volatile s8 vs8;
typedef volatile s16 vs16;
typedef volatile s32 vs32;
typedef volatile s64 vs64;
typedef float f32;
typedef double f64;
typedef volatile f32 vf32;
typedef volatile f64 vf64;
typedef int BOOL;
typedef unsigned int uintptr_t; // Manually added
// Pointer to unknown, to be determined at a later date.
typedef void* unkptr;
typedef u32 unknown;
#ifndef TRUE
#define TRUE 1
#endif // ifndef TRUE
#ifndef FALSE
#define FALSE 0
#endif // ifndef FALSE
#ifndef NULL
#define NULL ((void*)0)
#endif // ifndef NULL
#ifndef nullptr
#define nullptr 0
#endif // ifndef nullptr
// For functions that return 0 on a success and -1 on failure
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE -1
#endif // ifndef EXIT_SUCCESS
#define ASSERT_HANG(cond) \
if (!(cond)) { \
while (true) { } \
}
#endif

42
ldscript.lcf Normal file
View File

@ -0,0 +1,42 @@
MEMORY
{
text : origin = 0x80003100
}
SECTIONS
{
GROUP:
{
.init ALIGN(0x20):{}
/* TODO: should be extab and extabindex */
extab_ ALIGN(0x20):{}
extabindex_ ALIGN(0x20):{}
.text ALIGN(0x20):{}
.ctors ALIGN(0x20):{}
.dtors ALIGN(0x20):{}
.rodata ALIGN(0x20):{}
.data ALIGN(0x20):{}
.bss ALIGN(0x20):{}
.sdata ALIGN(0x20):{}
.sbss ALIGN(0x20):{}
.sdata2 ALIGN(0x20):{}
.sbss2 ALIGN(0x20):{}
.stack ALIGN(0x100):{}
} > text
/* Stack size upped from the default of 65535 */
_stack_addr = (_f_sbss2 + SIZEOF(.sbss2) + 68608 + 0x7) & ~0x7;
_stack_end = _f_sbss2 + SIZEOF(.sbss2);
_db_stack_addr = (_stack_addr + 0x2000);
_db_stack_end = _stack_addr;
__ArenaLo = (_db_stack_addr + 0x1f) & ~0x1f;
__ArenaHi = 0x81700000;
}
FORCEFILES
{
ctors.o
dtors.o
extab.o
extabindex.o
}

35
ldscript.ld Normal file
View File

@ -0,0 +1,35 @@
ENTRY(__start)
_SDA_BASE_ = 0x805AEBC0;
_SDA2_BASE_ = 0x805B1D20;
PHDRS
{
init PT_LOAD;
text PT_LOAD;
extab_ PT_LOAD;
extabindex_ PT_LOAD;
ctors PT_LOAD;
dtors PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;
bss PT_LOAD;
sdata PT_LOAD;
sbss PT_LOAD;
sdata2 PT_LOAD;
sbss2 PT_LOAD;
}
SECTIONS
{
.init 0x80003100 : { *(.init) } : init
.text 0x80003640 : { *(.text) } : text
extab_ 0x800035A0 : { *(extab_) } : extab_
extabindex_ 0x800035E0 : { *(extabindex_) } : extabindex_
.ctors 0x803CB1C0 : { *(.ctors) } : ctors
.dtors 0x803CB380 : { *(.dtors) } : dtors
.rodata 0x803CB3A0 : { *(.rodata) } : rodata
.data 0x803D8D60 : { *(.data) } : data
.bss 0x803F7560c (NOLOAD) : { *(.bss) } : bss
.sdata 0x805A6BC0 : { *(.sdata) } : sdata
.sbss 0x805A8C20 (NOLOAD) : { *(.sbss) } : sbss
.sdata2 0x805A9D20 : { *(.sdata2) } : sdata2
.sbss2 0x805AF460 (NOLOAD) : { *(.sbss2) } : sbss2
}

40
obj_files.mk Normal file
View File

@ -0,0 +1,40 @@
INIT_O_FILES :=\
$(BUILD_DIR)/src/os/__start.o\
$(BUILD_DIR)/asm/os/__ppc_eabi_init.o\
$(BUILD_DIR)/asm/Runtime/PPCEABI/H/__mem.o
TEXT_O_FILES :=\
$(BUILD_DIR)/asm/text.o
EXTAB_O_FILES :=\
$(BUILD_DIR)/asm/extab.o
EXTABINDEX_O_FILES :=\
$(BUILD_DIR)/asm/extabindex.o
CTORS_O_FILES :=\
$(BUILD_DIR)/asm/ctors.o
DTORS_O_FILES :=\
$(BUILD_DIR)/asm/dtors.o
RODATA_O_FILES :=\
$(BUILD_DIR)/asm/rodata.o
DATA_O_FILES :=\
$(BUILD_DIR)/asm/data.o
BSS_O_FILES :=\
$(BUILD_DIR)/asm/bss.o
SDATA_O_FILES :=\
$(BUILD_DIR)/asm/sdata.o
SBSS_O_FILES :=\
$(BUILD_DIR)/asm/sbss.o
SDATA2_O_FILES :=\
$(BUILD_DIR)/asm/sdata2.o
SBSS2_O_FILES :=\
$(BUILD_DIR)/asm/sbss2.o

1
sha1/mp1.0.sha1 Normal file
View File

@ -0,0 +1 @@
949c5ed7368aef547e0b0db1c3678f466e2afbff build/mp1.0/main.dol

171
src/os/__start.c Normal file
View File

@ -0,0 +1,171 @@
#include "Dolphin/__start.h"
#pragma section code_type ".init"
void __check_pad3(void)
{
if ((Pad3Button & 0x0eef) == 0x0eef) {
OSResetSystem(OS_RESET_RESTART, 0, FALSE);
}
return;
}
// clang-format off
__declspec (weak) asm void __start(void)
{
nofralloc
bl __init_registers
bl __init_hardware
li r0, -1
stwu r1, -8(r1)
stw r0, 4(r1)
stw r0, 0(r1)
bl __init_data
li r0, 0
lis r6, EXCEPTIONMASK_ADDR@ha
addi r6, r6, EXCEPTIONMASK_ADDR@l
stw r0, 0(r6)
lis r6, BOOTINFO2_ADDR@ha
addi r6, r6, BOOTINFO2_ADDR@l
lwz r6, 0(r6)
_check_TRK:
cmplwi r6, 0
beq _load_lomem_debug_flag
lwz r7, OS_BI2_DEBUGFLAG_OFFSET(r6)
b _check_debug_flag
_load_lomem_debug_flag:
lis r5, ARENAHI_ADDR@ha
addi r5, r5, ARENAHI_ADDR@l
lwz r5, 0(r5)
cmplwi r5, 0
beq _goto_main
lis r7, DEBUGFLAG_ADDR@ha
addi r7, r7, DEBUGFLAG_ADDR@l
lwz r7, 0(r7)
_check_debug_flag:
li r5, 0
cmplwi r7, 2
beq _goto_inittrk
cmplwi r7, 3
bne _goto_main
li r5, 1
_goto_inittrk:
lis r6, InitMetroTRK@ha
addi r6, r6, InitMetroTRK@l
mtlr r6
blrl
_goto_main:
lis r6, BOOTINFO2_ADDR@ha
addi r6, r6, BOOTINFO2_ADDR@l
lwz r5, 0(r6)
cmplwi r5, 0
beq+ _no_args
lwz r6, 8(r5)
cmplwi r6, 0
beq+ _no_args
add r6, r5, r6
lwz r14, 0(r6)
cmplwi r14, 0
beq _no_args
addi r15, r6, 4
mtctr r14
_loop:
addi r6, r6, 4
lwz r7, 0(r6)
add r7, r7, r5
stw r7, 0(r6)
bdnz _loop
lis r5, ARENAHI_ADDR@ha
addi r5, r5, ARENAHI_ADDR@l
rlwinm r7, r15, 0, 0, 0x1a
stw r7, 0(r5)
b _end_of_parseargs
_no_args:
li r14, 0
li r15, 0
_end_of_parseargs:
bl DBInit
bl OSInit
lis r4, DVD_DEVICECODE_ADDR@ha
addi r4, r4, DVD_DEVICECODE_ADDR@l
lhz r3, 0(r4)
andi. r5, r3, 0x8000
beq _check_pad3
andi. r3, r3, 0x7fff
cmplwi r3, 1
bne _goto_skip_init_bba
_check_pad3:
bl __check_pad3
_goto_skip_init_bba:
bl __init_user
mr r3, r14
mr r4, r15
bl main
b exit
}
asm static void __init_registers(void)
{
nofralloc
lis r1, _stack_addr@h
ori r1, r1, _stack_addr@l
lis r2, _SDA2_BASE_@h
ori r2, r2, _SDA2_BASE_@l
lis r13, _SDA_BASE_@h
ori r13, r13, _SDA_BASE_@l
blr
}
__declspec(section ".init") extern __rom_copy_info _rom_copy_info[];
__declspec(section ".init") extern __bss_init_info _bss_init_info[];
// clang-format on
inline static void __copy_rom_section(void* dst, const void* src, unsigned long size)
{
if (size && (dst != src)) {
memcpy(dst, src, size);
__flush_cache(dst, size);
}
}
inline static void __init_bss_section(void* dst, unsigned long size)
{
if (size) {
memset(dst, 0, size);
}
}
#pragma scheduling off
void __init_data(void)
{
__rom_copy_info* dci;
__bss_init_info* bii;
dci = _rom_copy_info;
while (TRUE) {
if (dci->size == 0)
break;
__copy_rom_section(dci->addr, dci->rom, dci->size);
dci++;
}
bii = _bss_init_info;
while (TRUE) {
if (bii->size == 0)
break;
__init_bss_section(bii->addr, bii->size);
bii++;
}
}

16
tools/Makefile Normal file
View File

@ -0,0 +1,16 @@
CC := gcc
CFLAGS := -O3 -Wall -s
default: all
all: elf2dol elf2rel
elf2dol: elf2dol.c
$(CC) $(CFLAGS) -o $@ $^
elf2rel: elf2rel.c
$(CC) $(CFLAGS) -o $@ $^
clean:
$(RM) elf2dol
$(RM) elf2rel

120
tools/deincbin.py Normal file
View File

@ -0,0 +1,120 @@
#!/usr/bin/env python3
#
# Usage: dump_common_data.py file.s
# Dumps all incbin data and prints the revised file to stdout.
import os
import re
import sys
# Reads a bytearray from baserom.dol
def read_baserom(start, size):
with open('baserom.dol', 'rb') as f:
f.seek(start, os.SEEK_SET)
return bytearray(f.read(size))
if len(sys.argv) != 2:
print('Usage: %s ASM_FILE' % sys.argv[0])
exit()
# reads a 32-bit big endian value starting at pos
def read_u32(data, pos):
return (data[pos]<<24) | (data[pos+1]<<16) | (data[pos+2]<<8) | (data[pos+3])
def is_ascii(code):
if code >= 0x20 and code <= 0x7E: # normal characters
return True
if code in [0x09, 0x0A]: # tab, newline
return True
return False
# reads a string starting at pos
def read_string(data, pos):
text = ''
while pos < len(data) and is_ascii(data[pos]):
text += chr(data[pos])
pos += 1
if pos < len(data) and data[pos] == 0:
return text
return ''
# escapes special characters in the string for use in a C string literal
def escape_string(text):
return text.replace('\\','\\\\').replace('"','\\"').replace('\n','\\n').replace('\t','\\t')
# returns True if value is 4-byte aligned
def is_aligned(num):
return num % 4 == 0
# returns True if value is a possible pointer
def is_pointer(num):
return num >= 0x80003100 and num <= 0x802F6C80
# returns True if all elements are zero
def is_all_zero(arr):
for val in arr:
if val != 0:
return False
return True
# returns string of comma-separated hex bytes
def hex_bytes(data):
return ', '.join('0x%02X' % n for n in data)
def convert_data(data, offset):
text = ''
size = len(data)
pos = 0
while pos < size:
# pad unaligned
pad = []
while not is_aligned(offset + pos) and pos < size:
pad.append(data[pos])
pos += 1
if len(pad) > 0:
if is_all_zero(pad):
text += '\t.balign 4\n'
else:
text += '\t.byte %s\n' % hex_bytes(pad)
# string?
string = read_string(data, pos)
if len(string) > 3:
text += '\t.asciz "%s"\n' % escape_string(string)
pos += len(string) + 1
continue
assert(is_aligned(offset + pos))
if pos + 4 <= size:
val = read_u32(data, pos)
if is_pointer(val):
text += '\t.4byte 0x%08X ;# ptr\n' % val
elif val == 0:
text += '\t.4byte 0\n'
else:
text += '\t.4byte 0x%08X\n' % val
pos += 4
return text
currSection = ''
with open(sys.argv[1], 'rt') as f:
for line in f.readlines():
line = line.rstrip()
# Section directive
m = re.match(r'\s*\.section\s+([\._A-Za-z0-9]+)', line)
if m:
currSection = m.groups()[0]
elif currSection in ['.rodata', '.data', '.sdata', '.sdata2', '.ctors', '.dtors', 'extab_', 'extabindex_']:
# Incbin directive
m = re.match(r'\s*\.incbin\s+"baserom.dol"\s*,\s*([^,]+),\s*([^,]+)', line)
if m:
g = m.groups()
start = int(g[0], 0)
size = int(g[1], 0)
data = read_baserom(start, size)
print('\t# ROM: 0x%X' % start)
print(convert_data(data, start))
continue
print(line)

497
tools/elf2dol.c Normal file
View File

@ -0,0 +1,497 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>
#ifndef MAX
//! Get the maximum of two values
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
//! Get the minimum of two values
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#define ARRAY_COUNT(arr) (sizeof(arr)/sizeof((arr)[0]))
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf32_Ehdr;
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_PAD 7
#define EI_NIDENT 16
#define ELFCLASS32 1
#define ELFDATA2MSB 2
#define EV_CURRENT 1
#define ET_EXEC 2
#define EM_PPC 20
typedef struct {
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
#define PT_LOAD 1
#define PF_R 4
#define PF_W 2
#define PF_X 1
int verbosity = 0;
#if BYTE_ORDER == BIG_ENDIAN
#define swap32(x) (x)
#define swap16(x) (x)
#else
static inline uint32_t swap32(uint32_t v)
{
return (v >> 24) |
((v >> 8) & 0x0000FF00) |
((v << 8) & 0x00FF0000) |
(v << 24);
}
static inline uint16_t swap16(uint16_t v)
{
return (v >> 8) | (v << 8);
}
#endif /* BIG_ENDIAN */
typedef struct {
uint32_t text_off[7];
uint32_t data_off[11];
uint32_t text_addr[7];
uint32_t data_addr[11];
uint32_t text_size[7];
uint32_t data_size[11];
uint32_t bss_addr;
uint32_t bss_size;
uint32_t entry;
uint32_t pad[7];
} DOL_hdr;
#define HAVE_BSS 1
#define MAX_TEXT_SEGMENTS 7
#define MAX_DATA_SEGMENTS 11
#define DOL_ALIGNMENT 32
#define DOL_ALIGN(x) (((x) + DOL_ALIGNMENT - 1) & ~(DOL_ALIGNMENT - 1))
typedef struct {
DOL_hdr header;
int text_cnt;
int data_cnt;
uint32_t text_elf_off[7];
uint32_t data_elf_off[11];
uint32_t flags;
FILE *elf;
} DOL_map;
void usage(const char *name)
{
fprintf(stderr, "Usage: %s [-h] [-v] [--] elf-file dol-file\n", name);
fprintf(stderr, " Convert an ELF file to a DOL file (by segments)\n");
fprintf(stderr, " Options:\n");
fprintf(stderr, " -h Show this help\n");
fprintf(stderr, " -v Be more verbose (twice for even more)\n");
}
#define die(x) { fprintf(stderr, x "\n"); exit(1); }
#define perrordie(x) { perror(x); exit(1); }
void ferrordie(FILE *f, const char *str)
{
if(ferror(f)) {
fprintf(stderr, "Error while ");
perrordie(str);
} else if(feof(f)) {
fprintf(stderr, "EOF while %s\n", str);
exit(1);
} else {
fprintf(stderr, "Unknown error while %s\n", str);
exit(1);
}
}
void add_bss(DOL_map *map, uint32_t paddr, uint32_t memsz)
{
if(map->flags & HAVE_BSS) {
uint32_t curr_start = swap32(map->header.bss_addr);
uint32_t curr_size = swap32(map->header.bss_size);
if (paddr < curr_start)
map->header.bss_addr = swap32(paddr);
// Total BSS size should be the end of the last bss section minus the
// start of the first bss section.
if (paddr + memsz > curr_start + curr_size)
map->header.bss_size = swap32(paddr + memsz - curr_start);
} else {
map->header.bss_addr = swap32(paddr);
map->header.bss_size = swap32(memsz);
map->flags |= HAVE_BSS;
}
}
void read_elf_segments(DOL_map *map, const char *elf)
{
int read, i;
Elf32_Ehdr ehdr;
if(verbosity >= 2)
fprintf(stderr, "Reading ELF file...\n");
map->elf = fopen(elf, "rb");
if(!map->elf)
perrordie("Could not open ELF file");
read = fread(&ehdr, sizeof(ehdr), 1, map->elf);
if(read != 1)
ferrordie(map->elf, "reading ELF header");
if(memcmp(&ehdr.e_ident[0], "\177ELF", 4))
die("Invalid ELF header");
if(ehdr.e_ident[EI_CLASS] != ELFCLASS32)
die("Invalid ELF class");
if(ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
die("Invalid ELF byte order");
if(ehdr.e_ident[EI_VERSION] != EV_CURRENT)
die("Invalid ELF ident version");
if(swap32(ehdr.e_version) != EV_CURRENT)
die("Invalid ELF version");
if(swap16(ehdr.e_type) != ET_EXEC)
die("ELF is not an executable");
if(swap16(ehdr.e_machine) != EM_PPC)
die("Machine is not PowerPC");
if(!swap32(ehdr.e_entry))
die("ELF has no entrypoint");
map->header.entry = ehdr.e_entry;
if(verbosity >= 2)
fprintf(stderr, "Valid ELF header found\n");
uint16_t phnum = swap16(ehdr.e_phnum);
uint32_t phoff = swap32(ehdr.e_phoff);
Elf32_Phdr *phdrs;
if(!phnum || !phoff)
die("ELF has no program headers");
if(swap16(ehdr.e_phentsize) != sizeof(Elf32_Phdr))
die("Invalid program header entry size");
phdrs = malloc(phnum * sizeof(Elf32_Phdr));
if(fseek(map->elf, phoff, SEEK_SET) < 0)
ferrordie(map->elf, "reading ELF program headers");
read = fread(phdrs, sizeof(Elf32_Phdr), phnum, map->elf);
if(read != phnum)
ferrordie(map->elf, "reading ELF program headers");
for(i=0; i<phnum; i++) {
if(swap32(phdrs[i].p_type) == PT_LOAD) {
uint32_t offset = swap32(phdrs[i].p_offset);
uint32_t paddr = swap32(phdrs[i].p_vaddr);
uint32_t filesz = swap32(phdrs[i].p_filesz);
uint32_t memsz = swap32(phdrs[i].p_memsz);
uint32_t flags = swap32(phdrs[i].p_flags);
if(memsz) {
if(verbosity >= 2)
fprintf(stderr, "PHDR %d: 0x%x [0x%x] -> 0x%08x [0x%x] flags 0x%x\n",
i, offset, filesz, paddr, memsz, flags);
if(flags & PF_X) {
// TEXT segment
if(!(flags & PF_R))
fprintf(stderr, "Warning: non-readable segment %d\n", i);
if(flags & PF_W)
fprintf(stderr, "Warning: writable and executable segment %d\n", i);
if(filesz > memsz) {
fprintf(stderr, "Error: TEXT segment %d memory size (0x%x) smaller than file size (0x%x)\n",
i, memsz, filesz);
exit(1);
} else if (memsz > filesz) {
add_bss(map, paddr + filesz, memsz - filesz);
}
if(map->text_cnt >= MAX_TEXT_SEGMENTS) {
die("Error: Too many TEXT segments");
}
map->header.text_addr[map->text_cnt] = swap32(paddr);
map->header.text_size[map->text_cnt] = swap32(filesz);
map->text_elf_off[map->text_cnt] = offset;
map->text_cnt++;
} else {
// DATA or BSS segment
if(!(flags & PF_R))
fprintf(stderr, "Warning: non-readable segment %d\n", i);
if(filesz == 0) {
// BSS segment
add_bss(map, paddr, memsz);
} else {
// DATA segment
if(filesz > memsz) {
fprintf(stderr, "Error: segment %d memory size (0x%x) is smaller than file size (0x%x)\n",
i, memsz, filesz);
exit(1);
}
if(map->data_cnt >= MAX_DATA_SEGMENTS) {
die("Error: Too many DATA segments");
}
map->header.data_addr[map->data_cnt] = swap32(paddr);
map->header.data_size[map->data_cnt] = swap32(filesz);
map->data_elf_off[map->data_cnt] = offset;
map->data_cnt++;
}
}
} else {
if(verbosity >= 1)
fprintf(stderr, "Skipping empty program header %d\n", i);
}
} else if(verbosity >= 1) {
fprintf(stderr, "Skipping program header %d of type %d\n", i, swap32(phdrs[i].p_type));
}
}
if(verbosity >= 2) {
fprintf(stderr, "Segments:\n");
for(i=0; i<map->text_cnt; i++) {
fprintf(stderr, " TEXT %d: 0x%08x [0x%x] from ELF offset 0x%x\n",
i, swap32(map->header.text_addr[i]), swap32(map->header.text_size[i]),
map->text_elf_off[i]);
}
for(i=0; i<map->data_cnt; i++) {
fprintf(stderr, " DATA %d: 0x%08x [0x%x] from ELF offset 0x%x\n",
i, swap32(map->header.data_addr[i]), swap32(map->header.data_size[i]),
map->data_elf_off[i]);