mirror of https://github.com/zeldaret/oot.git
Fix update, remove _RomPos from linker script
This commit is contained in:
parent
a1ef3d254c
commit
acf082aef0
11
Makefile
11
Makefile
|
|
@ -847,7 +847,7 @@ $(ROMC): $(ROM) $(ELF) $(BUILD_DIR)/compress_ranges.txt
|
|||
|
||||
COM_PLUGIN := tools/com-plugin/common-plugin.so
|
||||
|
||||
LDFLAGS := -T $(LDSCRIPT) -T $(BUILD_DIR)/linker_scripts/makerom.ld -T $(BUILD_DIR)/undefined_syms.txt --no-check-sections --accept-unknown-input-arch --emit-relocs -Map $(MAP)
|
||||
LDFLAGS := -T $(LDSCRIPT) -T $(BUILD_DIR)/linker_scripts/makerom.ld -T $(BUILD_DIR)/undefined_syms.txt --emit-relocs -Map $(MAP)
|
||||
ifeq ($(PLATFORM),IQUE)
|
||||
ifeq ($(NON_MATCHING),0)
|
||||
LDFLAGS += -plugin $(COM_PLUGIN) -plugin-opt order=$(BASEROM_DIR)/bss-order.txt
|
||||
|
|
@ -857,6 +857,7 @@ endif
|
|||
|
||||
$(ELF): $(TEXTURE_FILES_OUT) $(ASSET_FILES_OUT) $(O_FILES) $(SEGMENT_FILES) $(OVL_RELOC_FILES) $(LDSCRIPT) \
|
||||
$(BUILD_DIR)/linker_scripts/makerom.ld $(BUILD_DIR)/undefined_syms.txt \
|
||||
$(BUILD_DIR)/src/makerom/rom_header.o $(BUILD_DIR)/src/makerom/ipl3.o $(BUILD_DIR)/src/makerom/entry.o \
|
||||
$(SAMPLEBANK_O_FILES) $(SOUNDFONT_O_FILES) $(SEQUENCE_O_FILES) \
|
||||
$(BUILD_DIR)/assets/audio/sequence_font_table.o $(BUILD_DIR)/assets/audio/audiobank_padding.o
|
||||
$(LD) $(LDFLAGS) -o $@
|
||||
|
|
@ -876,12 +877,12 @@ $(O_FILES): | asset_files
|
|||
$(BUILD_DIR)/spec: $(SPEC) $(SPEC_INCLUDES)
|
||||
$(CPP) $(CPPFLAGS) -MD -MP -MF $@.d -MT $@ -I. $< | $(BUILD_DIR_REPLACE) > $@
|
||||
|
||||
$(LDSCRIPT): $(BUILD_DIR)/$(SPEC)
|
||||
$(MKLDSCRIPT) $< $@ $(SEGMENTS_DIR)
|
||||
$(LDSCRIPT): $(BUILD_DIR)/spec
|
||||
$(MKLDSCRIPT) $< $@ $(BUILD_DIR)/src/makerom $(SEGMENTS_DIR)
|
||||
|
||||
# Generates a makefile containing rules for building .plf files
|
||||
# from overlay .o files for every overlay defined in the spec.
|
||||
$(SEGMENTS_DIR)/Makefile: $(BUILD_DIR)/$(SPEC)
|
||||
$(SEGMENTS_DIR)/Makefile: $(BUILD_DIR)/spec
|
||||
$(MKSPECRULES) $< $(SEGMENTS_DIR) $@
|
||||
|
||||
# Generates relocations for each overlay after partial linking so that the final
|
||||
|
|
@ -950,7 +951,7 @@ endif
|
|||
$(OBJDUMP_CMD)
|
||||
|
||||
$(BUILD_DIR)/src/makerom/ipl3.o: $(EXTRACTED_DIR)/incbin/ipl3
|
||||
$(OBJCOPY) -I binary -O elf32-big --rename-section .data=.text $< $@
|
||||
$(OBJCOPY) -I binary -O $(LD_OFORMAT) --rename-section .data=.text $< $@
|
||||
|
||||
$(BUILD_DIR)/src/%.o: src/%.s
|
||||
ifeq ($(COMPILER),ido)
|
||||
|
|
|
|||
26
spec/spec
26
spec/spec
|
|
@ -4,16 +4,6 @@
|
|||
|
||||
#include "include/versions.h"
|
||||
|
||||
beginseg
|
||||
name "makerom"
|
||||
// We set the address of the makerom segment as 0x80000400 - 0x1000, since the ROM header and IPL3 together
|
||||
// are 0x1000 bytes long and we want the entry code to end up at address 0x80000400.
|
||||
address 0x7FFFF400
|
||||
include "$(BUILD_DIR)/src/makerom/rom_header.o"
|
||||
include "$(BUILD_DIR)/src/makerom/ipl3.o"
|
||||
include "$(BUILD_DIR)/src/makerom/entry.o"
|
||||
endseg
|
||||
|
||||
beginseg
|
||||
name "boot"
|
||||
|
||||
|
|
@ -674,7 +664,7 @@ beginseg
|
|||
|
||||
// audio
|
||||
#if OOT_VERSION < NTSC_1_1 || !PLATFORM_N64
|
||||
pad_text
|
||||
include "$(BUILD_DIR)/__pad_text.o"
|
||||
#endif
|
||||
include "$(BUILD_DIR)/src/audio/internal/data.o"
|
||||
include "$(BUILD_DIR)/src/audio/internal/synthesis.o"
|
||||
|
|
@ -683,16 +673,16 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/audio/internal/thread.o"
|
||||
include "$(BUILD_DIR)/src/audio/internal/os.o"
|
||||
#if OOT_PAL_N64
|
||||
pad_text
|
||||
pad_text
|
||||
pad_text
|
||||
include "$(BUILD_DIR)/__pad_text.o"
|
||||
include "$(BUILD_DIR)/__pad_text.o"
|
||||
include "$(BUILD_DIR)/__pad_text.o"
|
||||
#endif
|
||||
include "$(BUILD_DIR)/src/audio/internal/playback.o"
|
||||
include "$(BUILD_DIR)/src/audio/internal/effects.o"
|
||||
include "$(BUILD_DIR)/src/audio/internal/seqplayer.o"
|
||||
include "$(BUILD_DIR)/src/audio/game/general.o"
|
||||
#if !PLATFORM_N64 && !DEBUG_FEATURES
|
||||
pad_text
|
||||
include "$(BUILD_DIR)/__pad_text.o"
|
||||
#endif
|
||||
include "$(BUILD_DIR)/src/audio/game/sfx_params.o"
|
||||
include "$(BUILD_DIR)/src/audio/game/sfx.o"
|
||||
|
|
@ -742,7 +732,9 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/libc64/malloc.o"
|
||||
include "$(BUILD_DIR)/src/libc64/qrand.o"
|
||||
include "$(BUILD_DIR)/src/libc64/__osMalloc_n64.o"
|
||||
#if !DEBUG_FEATURES
|
||||
include "$(BUILD_DIR)/src/libc64/sprintf.o"
|
||||
#endif
|
||||
include "$(BUILD_DIR)/src/libc64/aprintf.o"
|
||||
#elif PLATFORM_GC
|
||||
include "$(BUILD_DIR)/src/libc64/math64.o"
|
||||
|
|
@ -750,7 +742,9 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/libc64/malloc.o"
|
||||
include "$(BUILD_DIR)/src/libc64/qrand.o"
|
||||
include "$(BUILD_DIR)/src/libc64/__osMalloc_gc.o"
|
||||
#if !DEBUG_FEATURES
|
||||
include "$(BUILD_DIR)/src/libc64/sprintf.o"
|
||||
#endif
|
||||
include "$(BUILD_DIR)/src/libc64/aprintf.o"
|
||||
include "$(BUILD_DIR)/src/libc64/sleep.o"
|
||||
#elif PLATFORM_IQUE
|
||||
|
|
@ -761,7 +755,9 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/libc64/fp.o"
|
||||
include "$(BUILD_DIR)/src/libc64/qrand.o"
|
||||
include "$(BUILD_DIR)/src/libc64/sleep.o"
|
||||
#if !DEBUG_FEATURES
|
||||
include "$(BUILD_DIR)/src/libc64/sprintf.o"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// jpeg
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ int g_segmentsCount;
|
|||
|
||||
static void write_dmadata_table(FILE *fout)
|
||||
{
|
||||
int i;
|
||||
fprintf(fout, "DEFINE_DMA_ENTRY(makerom, \"makerom\")\n");
|
||||
|
||||
for (i = 0; i < g_segmentsCount; i++) {
|
||||
for (int i = 0; i < g_segmentsCount; i++) {
|
||||
// Don't emit dma entry for segments set with NOLOAD
|
||||
if (g_segments[i].flags & FLAG_NOLOAD) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -19,31 +19,58 @@ static void write_includes(const struct Segment *seg, FILE *fout, const char *se
|
|||
fprintf(fout, " %s/%s.plf (%s*)\n", segments_dir, seg->name, section);
|
||||
}
|
||||
|
||||
static void write_ld_script(FILE *fout, const char *segments_dir)
|
||||
static void write_ld_script(FILE *fout, uint32_t entrypoint_addr, const char *makerom_dir, const char *segments_dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
fputs("OUTPUT_ARCH (mips)\n"
|
||||
"\n"
|
||||
"SECTIONS\n"
|
||||
"{\n"
|
||||
" _RomPos = 0;\n"
|
||||
"\n",
|
||||
"{\n",
|
||||
fout);
|
||||
|
||||
fprintf(fout,
|
||||
" /* makerom */" "\n"
|
||||
"" "\n"
|
||||
" ..makerom.hdr 0 : AT(0)" "\n"
|
||||
" {" "\n"
|
||||
" %s/rom_header.o(.text*)" "\n"
|
||||
" %s/rom_header.o(.data*)" "\n"
|
||||
" %s/rom_header.o(.rodata*)" "\n"
|
||||
" }" "\n"
|
||||
" ..makerom.ipl 0 : AT(SIZEOF(..makerom.hdr))" "\n"
|
||||
" {" "\n"
|
||||
" %s/ipl3.o(.text*)" "\n"
|
||||
" %s/ipl3.o(.data*)" "\n"
|
||||
" %s/ipl3.o(.rodata*)" "\n"
|
||||
" }" "\n"
|
||||
" ..makerom.ent 0x%08X : AT(SIZEOF(..makerom.hdr) + SIZEOF(..makerom.ipl))" "\n"
|
||||
" {" "\n"
|
||||
" %s/entry.o(.text*)" "\n"
|
||||
" %s/entry.o(.data*)" "\n"
|
||||
" %s/entry.o(.rodata*)" "\n"
|
||||
" }" "\n"
|
||||
" _makeromSegmentRomStart = LOADADDR(..makerom.hdr);" "\n"
|
||||
" _makeromSegmentRomEnd = LOADADDR(..makerom.ent) + SIZEOF(..makerom.ent);" "\n"
|
||||
" _makeromSegmentRomSize = SIZEOF(..makerom.hdr) + SIZEOF(..makerom.ipl) + SIZEOF(..makerom.ent);" "\n"
|
||||
"" "\n",
|
||||
makerom_dir, makerom_dir, makerom_dir,
|
||||
makerom_dir, makerom_dir, makerom_dir,
|
||||
entrypoint_addr,
|
||||
makerom_dir, makerom_dir, makerom_dir
|
||||
);
|
||||
|
||||
const char *last_end = "makerom";
|
||||
uint32_t last_romalign = 0;
|
||||
|
||||
for (i = 0; i < g_segmentsCount; i++) {
|
||||
const struct Segment *seg = &g_segments[i];
|
||||
|
||||
fprintf(fout, " /* %s */\n\n", seg->name);
|
||||
|
||||
// align start of ROM segment
|
||||
if (seg->fields & (1 << STMT_romalign))
|
||||
fprintf(fout, " _RomPos = ALIGN(_RomPos, %i);\n", seg->romalign);
|
||||
|
||||
// Begin initialized data (.text, .data, .rodata)
|
||||
fprintf(fout, " _%sSegmentRomStartTemp = _RomPos;\n"
|
||||
" _%sSegmentRomStart = _%sSegmentRomStartTemp;\n"
|
||||
" ..%s ", seg->name, seg->name, seg->name, seg->name);
|
||||
|
||||
fprintf(fout, " ..%s ", seg->name);
|
||||
|
||||
if (seg->fields & (1 << STMT_after))
|
||||
// Continue after the requested segment, aligning to the required alignment for the new segment.
|
||||
|
|
@ -58,16 +85,20 @@ static void write_ld_script(FILE *fout, const char *segments_dir)
|
|||
// Continue after previous segment, aligning to the required alignment for the new segment.
|
||||
fprintf(fout, "ALIGN(0x%X)", seg->align);
|
||||
|
||||
// AT(_RomPos) isn't necessary, but adds useful "load address" lines to the map file.
|
||||
// AT(...) isn't necessary, but adds useful "load address" lines to the map file.
|
||||
// Also force an alignment of at least 0x10 at the start of any segment. This is especially important for
|
||||
// overlays as the final link step must not introduce alignment padding between the SegmentTextStart symbol
|
||||
// and the section contents as this would cause all generated relocations done prior to be wrong.
|
||||
fprintf(fout, " : AT(_RomPos)\n"
|
||||
" {\n"
|
||||
uint32_t next_romalign = (seg->fields & (1 << STMT_romalign)) ? seg->romalign : 0x10;
|
||||
fprintf(fout, " : AT(ALIGN(_%sSegmentRomEnd, %u))\n", last_end,
|
||||
(last_romalign > next_romalign) ? last_romalign : next_romalign);
|
||||
last_romalign = next_romalign;
|
||||
|
||||
fprintf(fout, " {\n"
|
||||
" . = ALIGN(0x10);\n"
|
||||
" _%sSegmentStart = .;\n"
|
||||
"\n",
|
||||
seg->name);
|
||||
seg->name);
|
||||
|
||||
// Write .text
|
||||
fprintf(fout, " _%sSegmentTextStart = .;\n", seg->name);
|
||||
|
|
@ -106,31 +137,25 @@ static void write_ld_script(FILE *fout, const char *segments_dir)
|
|||
"\n", seg->name, segments_dir, seg->name, seg->name, seg->name, seg->name, seg->name);
|
||||
}
|
||||
|
||||
const char *last_loadable = (seg->flags & FLAG_OVL) ? "Ovl" : "RoData";
|
||||
|
||||
// End initialized data.
|
||||
fprintf(fout, " }\n"
|
||||
" _RomPos += ( _%sSegment%sEnd - _%sSegmentTextStart );\n"
|
||||
" _%sSegmentRomEndTemp = _RomPos;\n"
|
||||
" _%sSegmentRomEnd = _%sSegmentRomEndTemp;\n"
|
||||
" _%sSegmentRomSize = ABSOLUTE( _%sSegmentRomEnd - _%sSegmentRomStart );\n"
|
||||
" _%sSegmentRomStart = LOADADDR(..%s);\n"
|
||||
" _%sSegmentRomEnd = LOADADDR(..%s) + SIZEOF(..%s);\n"
|
||||
" _%sSegmentRomSize = SIZEOF(..%s);\n"
|
||||
"\n",
|
||||
seg->name, last_loadable, seg->name, seg->name, seg->name, seg->name,
|
||||
seg->name, seg->name, seg->name);
|
||||
|
||||
// Align end of ROM segment
|
||||
if (seg->fields & (1 << STMT_romalign))
|
||||
fprintf(fout, " _RomPos = ALIGN(_RomPos, %i);\n", seg->romalign);
|
||||
seg->name, seg->name,
|
||||
seg->name, seg->name, seg->name,
|
||||
seg->name, seg->name);
|
||||
|
||||
// Begin uninitialized data (.bss, COMMON)
|
||||
// Note we must enforce a minimum alignment of at least 8 for
|
||||
// bss sections due to how bss is cleared in steps of 8 in
|
||||
// entry.s, and more widely it's more efficient.
|
||||
fprintf(fout, " ..%s.bss (NOLOAD) :\n"
|
||||
fprintf(fout, " ..%s.bss (NOLOAD) : AT(_%sSegmentRomEnd)\n"
|
||||
" {\n"
|
||||
" . = ALIGN(8);\n"
|
||||
" _%sSegmentBssStart = .;\n",
|
||||
seg->name, seg->name);
|
||||
seg->name, seg->name, seg->name);
|
||||
|
||||
// Write .bss and COMMON
|
||||
write_includes(seg, fout, segments_dir, ".bss");
|
||||
|
|
@ -145,9 +170,11 @@ static void write_ld_script(FILE *fout, const char *segments_dir)
|
|||
" }\n"
|
||||
"\n",
|
||||
seg->name, seg->name, seg->name, seg->name, seg->name);
|
||||
|
||||
last_end = seg->name;
|
||||
}
|
||||
|
||||
fputs(" _RomSize = _RomPos;\n\n", fout);
|
||||
fprintf(fout, " _RomSize = ALIGN(_%sSegmentRomEnd, %u);\n\n", last_end, last_romalign);
|
||||
|
||||
// Debugging sections
|
||||
fputs(
|
||||
|
|
@ -222,9 +249,10 @@ static void write_ld_script(FILE *fout, const char *segments_dir)
|
|||
static void usage(const char *execname)
|
||||
{
|
||||
fprintf(stderr, "Nintendo 64 linker script generation tool v0.04\n"
|
||||
"usage: %s SPEC_FILE LD_SCRIPT SEGMENTS_DIR\n"
|
||||
"usage: %s SPEC_FILE LD_SCRIPT SEGMENTS_DIR MAKEROM_DIR\n"
|
||||
"SPEC_FILE file describing the organization of object files into segments\n"
|
||||
"LD_SCRIPT filename of output linker script\n"
|
||||
"MAKEROM_DIR dir name containing makerom build objects\n"
|
||||
"SEGMENTS_DIR dir name containing partially linked overlay segments\n",
|
||||
execname);
|
||||
}
|
||||
|
|
@ -235,7 +263,7 @@ int main(int argc, char **argv)
|
|||
void *spec;
|
||||
size_t size;
|
||||
|
||||
if (argc != 4) {
|
||||
if (argc != 5) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
@ -246,7 +274,9 @@ int main(int argc, char **argv)
|
|||
ldout = fopen(argv[2], "w");
|
||||
if (ldout == NULL)
|
||||
util_fatal_error("failed to open file '%s' for writing", argv[2]);
|
||||
write_ld_script(ldout, argv[3]);
|
||||
|
||||
uint32_t entrypoint_addr = 0x80000400;
|
||||
write_ld_script(ldout, entrypoint_addr, argv[3], argv[4]);
|
||||
fclose(ldout);
|
||||
|
||||
free_rom_spec(g_segments, g_segmentsCount);
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ static void write_overlay_rules(FILE *fout, const char *ovls_dir)
|
|||
fprintf(fout, "%s/%s.plf:", ovls_dir, seg->name);
|
||||
for (j = 0; j < seg->includesCount; j++)
|
||||
fprintf(fout, " \\\n\t\t%s", seg->includes[j].fpath);
|
||||
fprintf(fout, " \\\n\t\t$(SEGMENTS_DIR)/Makefile");
|
||||
fprintf(fout, "\n"
|
||||
"\t@echo Linking \"%s\"\n"
|
||||
"\t$(SEG_VERBOSE)$(LD) $(SEG_LDFLAGS) $^ -o $@\n"
|
||||
"\t$(SEG_VERBOSE)$(LD) $(SEG_LDFLAGS) $(filter %%.o, $^) -o $@\n"
|
||||
"\n", seg->name);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue