diff --git a/MakeAPPL/main.cc b/MakeAPPL/main.cc index 3b4db468b3..4218ed1ec9 100644 --- a/MakeAPPL/main.cc +++ b/MakeAPPL/main.cc @@ -147,9 +147,9 @@ int main(int argc, char *argv[]) longword(code1, 0x61000002); // bsr *+2 word(code1, 0x0697); // addi.l #_, (a7) - longword(code1, entrypoint + 8); + longword(code1, entrypoint + 12); word(code1, 0x4e75); // rts - + longword(code1, code1.tellp() + 4); code1 << flt; rsrc.addResource(Resource("CODE", 1, code1.str())); diff --git a/Samples/SystemExtension/SystemExtension.r b/Samples/SystemExtension/SystemExtension.r index a595c40546..07dee8fc29 100644 --- a/Samples/SystemExtension/SystemExtension.r +++ b/Samples/SystemExtension/SystemExtension.r @@ -1,13 +1,15 @@ -type 'INIT' (0) { +type 'INIT' { hex string dontBreakAtEntry = $"", breakAtEntry = $"A9FF"; longint = 0x61000002; // bsr *+2 +relativeTo: integer = 0x0697; // addi.l #_, (a7) - longint = $$long(fltfile + 8*8) + 8; + longint = $$long(fltfile + 8*8) + (fltfile-relativeTo)/8; integer = 0x4e75; // rts + longint = fltfile/8; fltfile: hex string; }; -resource 'INIT' (0) { +resource 'INIT' (128) { dontBreakAtEntry, $$read("SystemExtension.flt"); }; diff --git a/libretro/Retro68Runtime.h b/libretro/Retro68Runtime.h index a9a83996e1..8a8f96bdad 100644 --- a/libretro/Retro68Runtime.h +++ b/libretro/Retro68Runtime.h @@ -23,16 +23,22 @@ . */ -#define RETRO68_GET_DISPLACEMENT(DISPLACEMENT) \ +#define _RETRO68_GET_DISPLACEMENT(DISPLACEMENT, STRIP) \ do { \ - long virtualstart, realstart; \ + char *virtualstart, *realstart; \ __asm__( "1:\n" \ "\tmove.l #1b, %0\n" \ "\tlea (1b:w,%%pc), %1" \ : "=r"(virtualstart) , "=a"(realstart) ); \ - DISPLACEMENT = realstart - virtualstart; \ + DISPLACEMENT = STRIP(realstart) - virtualstart; \ } while(0) +#define RETRO68_GET_DISPLACEMENT(DISPLACEMENT) \ + _RETRO68_GET_DISPLACEMENT(DISPLACEMENT, ) + +#define RETRO68_GET_DISPLACEMENT_STRIP(DISPLACEMENT) \ + _RETRO68_GET_DISPLACEMENT(DISPLACEMENT, StripAddress) + #define RETRO68_CALL_UNRELOCATED(FUN,ARGS) \ do { \ long displacement; \ diff --git a/libretro/relocate.c b/libretro/relocate.c index 97343b9210..d5bc3110f1 100644 --- a/libretro/relocate.c +++ b/libretro/relocate.c @@ -65,8 +65,9 @@ extern void __fini_section_end(void); -static long headerVirtualAddress = -0x40; +static long headerVirtualAddress = -sizeof(struct flat_hdr); static Ptr bssPtr = (Ptr) -1; +static Handle codeHandle = NULL; #define ACCESS_DISPLACED(VAR) \ ( * (typeof(&VAR)) ((char*)(&VAR) + displacement) ) @@ -74,9 +75,35 @@ static Ptr bssPtr = (Ptr) -1; void Retro68Relocate() { long displacement; - RETRO68_GET_DISPLACEMENT(displacement); + RETRO68_GET_DISPLACEMENT_STRIP(displacement); - struct flat_hdr *header = (struct flat_hdr*) (ACCESS_DISPLACED(headerVirtualAddress) + displacement); + if(displacement == 0) + { + if(bssPtr != (Ptr) -1) + { + // this is not the first time, no relocations needed. + // should only happen for code resources. + HLock(codeHandle); + return; + } + } + + long headerOldVirtualAddress = ACCESS_DISPLACED(headerVirtualAddress); + struct flat_hdr *header = (struct flat_hdr*) (headerOldVirtualAddress + displacement); + uint8_t *base = (uint8_t*) (header+1); + + uint32_t headerOffsetInResource = ((uint32_t*)header)[-1]; + + if(headerOffsetInResource < 4096) + // Arbitrary magic number. We expect the offset to be small, just a few header bytes before it. + { + Handle h = RecoverHandle((Ptr) header - headerOffsetInResource); + if(MemError() == noErr && h) + { + HLock(h); + ACCESS_DISPLACED(codeHandle) = h; + } + } SysEnvRec env; long bss_size; @@ -89,7 +116,8 @@ void Retro68Relocate() long n = header->reloc_count; long *relocs = (long*)( (char*)header + header->reloc_start ); long i; - long data_end = header->data_end - 0x40; + long data_end = header->data_end + headerOldVirtualAddress; + uint32_t flt_size = (uint32_t) header->data_end; long bss_displacement = 0; Ptr bss = ACCESS_DISPLACED(bssPtr); @@ -105,17 +133,19 @@ void Retro68Relocate() for(i = 0; i < n; i++) { - uint8_t *addrPtr = (uint8_t*)(relocs[i] + displacement); - long addr; + uint8_t *addrPtr = base + relocs[i]; + uint32_t addr; - addr = (addrPtr[0] << 24) | (addrPtr[1] << 16) | (addrPtr[2] << 8) | addrPtr[3]; + //addr = *(uint32_t*)addrPtr; + addr = (((((addrPtr[0] << 8) | addrPtr[1]) << 8) | addrPtr[2]) << 8) | addrPtr[3]; - addr += addr >= data_end ? bss_displacement : displacement; + addr += (uint32_t)(addr - headerOldVirtualAddress) >= flt_size ? bss_displacement : displacement; - addrPtr[0] = addr >> 24; - addrPtr[1] = addr >> 16; - addrPtr[2] = addr >> 8; addrPtr[3] = addr; + addrPtr[2] = (addr >>= 8); + addrPtr[1] = (addr >>= 8); + addrPtr[0] = (addr >>= 8); + //*(uint32_t*)addrPtr = addr; } if(env.processor >= env68040)