diff --git a/libretro/Makefile b/libretro/Makefile new file mode 100644 index 0000000000..ceb7330e9c --- /dev/null +++ b/libretro/Makefile @@ -0,0 +1,19 @@ +PREFIX=/media/LinuxHD/wolfgang/Projects/Retro68-build/toolchain +CC=${PREFIX}/bin/m68k-unknown-elf-gcc +LD=${PREFIX}/bin/m68k-unknown-elf-ld +AR=${PREFIX}/bin/m68k-unknown-elf-ar + +CFLAGS=-O +OBJS=glue.o malloc.o syscalls.o start.o + +all: retrocrt.o libretro.a + +libretro.a: ${OBJS} + ${AR} cqs $@ ${OBJS} + +retrocrt.o: ${OBJS} + ${LD} -r -o $@ ${OBJS} + +.PHONY: install +install: retrocrt.o + cp $< ${PREFIX}/m68k-unknown-elf/lib/ diff --git a/libretro/glue.c b/libretro/glue.c new file mode 100644 index 0000000000..0bb40ef2d0 --- /dev/null +++ b/libretro/glue.c @@ -0,0 +1,15 @@ +#include + +Size GetPtrSize(Ptr ptr) +{ + long tmp; + __asm__ __volatile__( + "move.l %1, %%a0\n\t" + "dc.w 0xA021\n\t" + "move.l %%d0, %1" + : "=g"(tmp) : "g"(ptr) : "%%a0", "%%d0"); + if(tmp > 0) + return (Size) tmp; + else + return 0; +} diff --git a/libretro/malloc.c b/libretro/malloc.c new file mode 100644 index 0000000000..09b966ebae --- /dev/null +++ b/libretro/malloc.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +void referenceMyMalloc() {} + +void *_malloc_r(struct _reent *reent_ptr, size_t sz) +{ + return NewPtr(sz); // TODO: set errno +} +void *_calloc_r(struct _reent *reent_ptr, size_t sz, size_t sz2) +{ + return NewPtrClear(sz*sz2); // TODO: set errno +} + +void _free_r(struct _reent *reent_ptr, void *ptr) +{ + if(ptr != NULL) + DisposePtr(ptr); +} + +void *_realloc_r(struct _reent *reent_ptr, void *ptr, size_t sz) +{ + if(ptr == NULL) + { + return NewPtr(sz); + } + else + { + MemError(); + SetPtrSize(ptr, sz); + if(MemError()) + { + size_t oldSz = GetPtrSize(ptr); + if(sz > oldSz) + { + void *newPtr = NewPtr(sz); + if(!newPtr) + { + errno = ENOMEM; + return NULL; + } + memcpy(newPtr, ptr, oldSz); + return newPtr; + } + else + { + errno = ENOMEM; + return NULL; + } + } + } +} + +void *malloc(size_t sz) +{ + return _malloc_r(_REENT, sz); +} + +void free(void *p) +{ + _free_r(_REENT, p); +} + +void *realloc(void *ptr, size_t sz) +{ + return _realloc_r(_REENT, ptr, sz); +} + +void *calloc(size_t sz1, size_t sz2) +{ + return _calloc_r(_REENT, sz1, sz2); +} diff --git a/libretro/start.c b/libretro/start.c new file mode 100644 index 0000000000..eb585bba12 --- /dev/null +++ b/libretro/start.c @@ -0,0 +1,86 @@ +#include +#include +#include + +int main(int argc, char* argv[]); + +struct flat_hdr { + char magic[4]; + unsigned long rev; /* version */ + unsigned long entry; /* Offset of first executable instruction + with text segment from beginning of file */ + unsigned long data_start; /* Offset of data segment from beginning of + file */ + unsigned long data_end; /* Offset of end of data segment + from beginning of file */ + unsigned long bss_end; /* Offset of end of bss segment from beginning + of file */ + + /* (It is assumed that data_end through bss_end forms the bss segment.) */ + + unsigned long stack_size; /* Size of stack, in bytes */ + unsigned long reloc_start; /* Offset of relocation records from + beginning of file */ + unsigned long reloc_count; /* Number of relocation records */ + unsigned long flags; + unsigned long filler[6]; /* Reserved, set to zero */ +}; + +typedef void (*voidFunction)(void); +//extern voidFunction __init_array_start[]; +//extern voidFunction __init_array_end[]; +extern void __init_section(void); +extern void __init_section_end(void); +extern void __fini_section(void); +extern void __fini_section_end(void); + + + +void _start() +{ + char *argv[2] = { "./a.out", NULL }; + + + long virtualstart, realstart; + + __asm__( "move.l #_start, %0" : "=r"(virtualstart) ); + __asm__( "lea (_start:w,%%pc), %0" : "=a"(realstart) ); + + long displacement = realstart - virtualstart; + + struct flat_hdr *header = (struct flat_hdr*) (displacement - 0x40); + + Ptr bss = NewPtrClear(header->bss_end - header->data_end); + + long n = header->reloc_count; + long *relocs = (long*)( (char*)header + header->reloc_start ); + long i; + long data_end = header->data_end - 0x40; + long bss_displacement = (long)bss - data_end; + + for(i = 0; i < n; i++) + { + long *addr = (long*)(relocs[i] + displacement); + *addr += (*addr >= data_end ? bss_displacement : displacement); + } + + /* { + voidFunction *p; + for(p = __init_array_start; p < __init_array_end; ++p) + (**p)(); + }*/ + //__init_section(); + { + char *p = (char*)&__init_section; + char *e = (char*)&__init_section_end; + p += 2; + while( p < e ) + { + (*(voidFunction)(*(long*)p))(); + p += 6; + } + } + + main(displacement, argv); + ExitToShell(); +} diff --git a/libretro/syscalls.c b/libretro/syscalls.c new file mode 100644 index 0000000000..a7778e1fa4 --- /dev/null +++ b/libretro/syscalls.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +int isatty(int fd) { return fd >= 0 && fd <= 2; } +void *sbrk(long increment) +{ + Debugger(); + return NewPtrClear(increment); +} + +void _exit(int status) +{ + if(status != 0) + Debugger(); + ExitToShell(); + for(;;) + ; +} + +ssize_t (*__write_hook)(int fd, const void*buf, size_t count) = NULL; + +ssize_t write(int fd, const void *buf, size_t count) +{ + if(__write_hook) + return (*__write_hook)(fd,buf,count); + return -1; +} + +ssize_t read(int fd, void *buf, size_t count) +{ + return -1; +} + +int open(const char* name, int flags, mode_t mode) +{ + __asm__ __volatile__ ("dc.w 0xa9ff"); + return -1; +} + +int close(int fd) +{ + return -1; +} + +int fstat(int fd, struct stat *buf) +{ + return -1; +} + +off_t lseek(int fd, off_t offset, int whence) +{ + return (off_t) -1; +} + +int kill(pid_t pid, int sig) +{ + if(pid == 42) + _exit(42); + else + return -1; +} + +pid_t getpid(void) +{ + return 42; +}