diff --git a/Elf2Mac/Elf2Mac.cc b/Elf2Mac/Elf2Mac.cc index 4738aa28b0..648999ad3c 100644 --- a/Elf2Mac/Elf2Mac.cc +++ b/Elf2Mac/Elf2Mac.cc @@ -48,13 +48,8 @@ using std::shared_ptr; using std::make_shared; using std::unique_ptr; -unordered_map codeSections; -unordered_map relaSections; -Elf_Scn* dataSection; -Elf_Scn* bssSection; -Elf_Scn *symtabSection; size_t sectionHeaderStringTableIdx; -size_t mainStringTableIdx; +size_t mainStringTableIdx = (size_t)-1; class Symtab; @@ -175,7 +170,7 @@ void GrokELF(string input) GElf_Ehdr ehdr; gelf_getehdr(elf, &ehdr); - unordered_map progbits; + Elf_Scn* bssSection = NULL; int idx = 0; for(Elf_Scn *scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL;idx++) @@ -201,7 +196,6 @@ void GrokELF(string input) if(boost::algorithm::starts_with(name,".rela.")) { string progbitsName = name.substr(5); - relaSections[progbitsName] = scn; assert(sections.find(progbitsName) != sections.end()); sections[progbitsName]->SetRela(scn); } @@ -209,27 +203,24 @@ void GrokELF(string input) if(shdr.sh_type == SHT_PROGBITS && !bssSection) // ignore everything after bss, that's just debug info { - codeSections[name] = scn; sections.emplace(name, make_shared
(idx, scn)); } if(shdr.sh_type == SHT_NOBITS) { bssSection = scn; + // Currently, the bss section is only used here + // to know when to start skipping debug info sections. + // (What's the official way to distinguish a debug info section from a "real" section?) + + // We don't even need to remember the size of address of the bss segment, + // the initialization code in libretro/relocate.c knows this from + // the _sbss and _ebss symbols defined in the linker script. } } } -void ElfToFlt(string input, string output) +void FlatCode(std::ostream& out) { - GrokELF(input); - - GElf_Shdr text_shdr, data_shdr, bss_shdr; - gelf_getshdr(codeSections[".text"], &text_shdr); - gelf_getshdr(codeSections[".data"], &data_shdr); - gelf_getshdr(bssSection, &bss_shdr); - - ofstream out(output); - out << sections[".text"]->GetData(); out << sections[".data"]->GetData(); @@ -238,6 +229,74 @@ void ElfToFlt(string input, string output) longword(out, -1); } +void FlatCode(string fn) +{ + ofstream out(fn); + FlatCode(out); +} + + +std::string fromhex(std::string hex) +{ + std::string bin; + int nibble; + bool haveNibble = false; + for(std::string::iterator p = hex.begin(); p != hex.end(); ++p) + { + if(std::isspace(*p)) + continue; + assert(isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f')); + int digit; + if(isdigit(*p)) + digit = *p - '0'; + else + digit = tolower(*p) - 'a' + 0xA; + + if(haveNibble) + { + bin += (char) ((nibble << 4) | digit); + haveNibble = false; + } + else + { + nibble = digit; + haveNibble = true; + } + } + return bin; +} + + + +void SingleSegmentApp(string output) +{ + ResourceFile file(output); + Resources& rsrc = file.resources; + + rsrc.addResource(Resource(ResType("CODE"), 0, + fromhex( + "00000028 00000000 00000008 00000020" + "0000 3F3C 0001 A9F0" + ) + )); + + + { + std::ostringstream code1; + word(code1, 0); + word(code1, 1); + FlatCode(code1); + + rsrc.addResource(Resource(ResType("CODE"), 1, + code1.str())); + } + + file.creator = ResType("????"); + file.type = ResType("APPL"); + + file.write(); +} + string argvZero; void RealLD(vector args) @@ -293,6 +352,7 @@ int main(int argc, char *argv[]) { string outputFile = "a.out"; bool elf2mac = false; + bool flatoutput = false; vector args2; for(auto p = args.begin(), e = args.end(); p != e; ++p) @@ -312,6 +372,11 @@ int main(int argc, char *argv[]) { elf2mac = true; } + else if(*p == "--mac-flat") + { + elf2mac = true; + flatoutput = true; + } else { args2.push_back(*p); @@ -334,7 +399,11 @@ int main(int argc, char *argv[]) args2.push_back(tmpfile); RealLD(args2); unlink(tmpfile); - ElfToFlt(outputFile + ".gdb", outputFile); + GrokELF(outputFile + ".gdb"); + if(flatoutput) + FlatCode(outputFile); + else + SingleSegmentApp(outputFile); } else { @@ -346,7 +415,8 @@ int main(int argc, char *argv[]) { if(argc != 2) errx(EXIT_FAILURE, "usage : %s file-name ", argv[0]); - ElfToFlt(argv[1], "out.flt"); + GrokELF(argv[1]); + FlatCode("out.flt"); } return 0; } diff --git a/Samples/SystemExtension/CMakeLists.txt b/Samples/SystemExtension/CMakeLists.txt index f0ef96738e..65be679085 100644 --- a/Samples/SystemExtension/CMakeLists.txt +++ b/Samples/SystemExtension/CMakeLists.txt @@ -1,26 +1,53 @@ +# Copyright 2017 Wolfgang Thaller. +# +# This file is part of Retro68. +# +# Retro68 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Retro68 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Retro68. If not, see . + +# Here's how to build a system extension, a.k.a. an INIT. +# The same applies to various other kinds of code resources. + +# PowerPC is not currently supported here. +# As for Carbon, there are no code resources anyway. + +# Step 1: +# Build the code resource as a regular executable +# (not using the add_application macro) add_executable(SystemExtension SystemExtension.c - SystemExtension.r ShowInitIcon.c + SystemExtension.r ShowInitIcon.h) -set_target_properties(SystemExtension PROPERTIES OUTPUT_NAME SystemExtension.flt) +set_target_properties(SystemExtension PROPERTIES + OUTPUT_NAME SystemExtension.flt + + # set a linker flag that says we want a flat piece + # of code in a data file + LINK_FLAGS -Wl,--mac-flat) + # Use Rez to put it together add_custom_command( OUTPUT SystemExtension.bin SystemExtension.dsk COMMAND ${REZ} -I ${REZ_INCLUDE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/SystemExtension.r --copy ${CMAKE_CURRENT_SOURCE_DIR}/Icons.rsrc.bin -o SystemExtension.bin - -t INIT - COMMAND ${REZ} --copy SystemExtension.bin - -o SystemExtension.dsk - -t INIT - COMMAND ${REZ} --copy SystemExtension.bin - -o SystemExtension + --cc SystemExtension.dsk + --cc SystemExtension -t INIT DEPENDS SystemExtension SystemExtension.r Icons.rsrc.bin) - add_custom_target(SystemExtension_INIT ALL DEPENDS SystemExtension.dsk) diff --git a/cmake/add_application.cmake b/cmake/add_application.cmake index 43616d2315..b8e94dda95 100644 --- a/cmake/add_application.cmake +++ b/cmake/add_application.cmake @@ -70,16 +70,16 @@ function(add_application name) if(CMAKE_SYSTEM_NAME MATCHES Retro68) - set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.flt) + set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.code.bin) add_custom_command( OUTPUT ${name}.bin ${name}.APPL ${name}.dsk ${name}.ad "%${name}.ad" COMMAND ${REZ} ${REZ_FLAGS} ${REZ_TEMPLATES_PATH}/Retro68APPL.r -I${REZ_INCLUDE_PATH} - -DFLT_FILE_NAME="\\"${name}.flt\\"" - -o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL" - --cc "%${name}.ad" + --copy "${name}.code.bin" + -o "${name}.bin" + --cc "${name}.dsk" --cc "${name}.APPL" --cc "%${name}.ad" -t ${ARGS_TYPE} -c ${ARGS_CREATOR} ${ARGS_MAKEAPPL_ARGS} DEPENDS ${name} ${rsrc_files}) diff --git a/libretro/Retro68APPL.r b/libretro/Retro68APPL.r index fe04df539c..0a340a906e 100644 --- a/libretro/Retro68APPL.r +++ b/libretro/Retro68APPL.r @@ -1,6 +1,13 @@ #include "Processes.r" #include "Retro68.r" +#if 0 +/* + * By default, Application CODE resources are no longer + * created by Rez, but rather by Elf2Mac. + * It is still possible to create a single-segment + * application this way, though. + */ resource 'CODE' (0) RETRO68_JUMP_TABLE; resource 'CODE' (1) { @@ -11,6 +18,7 @@ resource 'CODE' (1) { #endif $$read(FLT_FILE_NAME); }; +#endif resource 'SIZE' (-1) { dontSaveScreen,