gint: setup to prepare HH2 stage-2 loads

This commit is contained in:
Lephe 2024-06-02 22:01:29 +02:00
parent 84a4dd7ca9
commit 1fc7290b09
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
2 changed files with 62 additions and 10 deletions

View file

@ -35,8 +35,10 @@ SECTIONS
- Compiler-provided constructors (.ctors) and destructors (.dtors) - Compiler-provided constructors (.ctors) and destructors (.dtors)
- All text from .text and .text.* (including user code) */ - All text from .text and .text.* (including user code) */
.text : { .text : {
*(.text.header) KEEP(*(.hh2.header))
KEEP(*(.hh2info)) KEEP(*(.hh2.info))
KEEP(*(.hh2.stage2))
*(.text.entry) *(.text.entry)
_bctors = . ; _bctors = . ;

View file

@ -1,18 +1,68 @@
#include <gint/config.h> #include <gint/config.h>
#if GINT_OS_CP #if GINT_OS_CP
.section .text.header /*
Binary format for HollyHock-2. HH2 requires the following header layout:
0x00 (12 bytes): Entry point
0x0c (4 bytes): Load address
0x10 (variable): Metadata as NUL-terminated strings
Additionally, HH2 only loads up to 128 kB, so we need a second-stage loader to
handle larger programs. We'll generally want to load these to the VRAM backup,
i.e. not the default.
Since we need a stage-2 loader, we might as well (1) let HH2 do the short
stage-1 load to the end of the RAM, (2) use the stage-2 loader to load the rest
of the add-in into the VRAM backup, and (3) scrap the end-of-RAM area and use
it as buffer/heap.
The only subtlety is that the stage-2 loader must know the binary file's path
to load from the filesystem, and HollyHock doesn't (yet) give it to us. We
write the path in the final binary with the fxsdk/scripts/patch_hh2_filename.py
script from the fxSDK. This is fragile (i.e. not renaming-proof), but a start.
Since the header is variable-size, I leave the offset of stage-2 in the binary
at offset 0x06. I could avoid this by patching the ELF, not bin, but I'm lazy.
*/
/* 16-byte header */
.section .hh2.header, "ax"
.global _start_header .global _start_header
.align 2
_start_header: _start_header:
mov.l .start, r0 mov.l 1f, r0
jmp @r0 jmp @r0
nop nop
/* Offset to hardcoded filename, used to patch binary after linking */
.align 2 .word (.stage2_filename - _start_header)
.start: /* Address of stage-2 */
.long _start 1: .long _stage2
.load_addr: /* Stage-1 load address at end of RAM (specified in linker script) */
.long _start_header .long _start_header
#endif /* Note: User-provided, variable-size app metadata is linked in-between the
.hh2.header and the .hh2.stage2 sections */
/* Stage-2 loader */
.section .hh2.stage2, "ax"
.align 2
_stage2:
/* No-op load */
mov.l 1f, r0
jmp @r0
nop
nop
1: .long _start
.align 2
.zero 2
.stage2_path:
.ascii "\\fls0\\"
.stage2_filename:
/* Recognizable pattern so the patching script can double-check that
it's overriding the correct location. */
.long 1, 2, 3, 4, 5, 6, 7, 8
#endif /* GINT_OS_CP */