From 73f05a13c8eeb1079526f761cbd67912458168c5 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 15 Jan 2020 17:54:29 +0100 Subject: [PATCH] added pragma support to build_segment tool --- Makefile | 25 +++--- c64/kernal/banking/4000.mega65_kernal_1.s | 9 +- c64/kernal/banking/mega65_mapping.s | 12 +-- c64/kernal/init/fda3.ioinit.s | 6 ++ src/build_segment.cc | 103 ++++++++++++++++++++-- 5 files changed, 131 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index fe065856..d3ab3700 100644 --- a/Makefile +++ b/Makefile @@ -65,12 +65,12 @@ STD_TARGET_LIST_MEGA65 = build/kernal_mega65.rom_0 \ build/kernal_mega65.rom_1 \ build/basic_mega65.rom_0 -STD_TARGET_LIST = $(STD_TARGET_LIST_CUSTOM) \ +STD_TARGET_LIST = build/chargen.rom \ + $(STD_TARGET_LIST_CUSTOM) \ $(STD_TARGET_LIST_GENERIC) \ $(STD_TARGET_LIST_TESTING) \ $(STD_TARGET_LIST_MEGA65) \ - $(STD_TARGET_LIST_ULTIMATE64) \ - build/chargen.rom + $(STD_TARGET_LIST_ULTIMATE64) EXT_TARGET_LIST = build/mega65.rom @@ -222,7 +222,7 @@ build/target_mega65/OUTK_0.BIN build/target_mega65/KERNAL_0_combined.vs build/ta @rm -f $@* build/target_mega65/KERNAL_0* @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_0 -i KERNAL_0-mega65 -o OUTK_0.BIN -d build/target_mega65 -l e4d3 -h ffff c64/,,config_mega65.s $(SRCDIR_KERNAL) $(GEN_KERNAL) -build/kernal_mega65.rom_1 build/target_mega65/OUTK_1.BIN build/target_mega65/KERNAL_1_combined.vs build/target_mega65/KERNAL_1_combined.sym: +build/kernal_mega65.rom_1 build/target_mega65/OUTK_1.BIN build/target_mega65/KERNAL_1_combined.vs build/target_mega65/KERNAL_1_combined.sym: $(TOOL_BUILD_SEGMENT) @mkdir -p build/target_mega65 @rm -f $@* build/kernal_mega65.rom_1 build/target_mega65/KERNAL_1* @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_1 -i KERNAL_1-mega65 -o OUTK_1.BIN -d build/target_mega65 -l 4000 -h 5fff c64/,,config_mega65.s $(SRCDIR_KERNAL) $(GEN_KERNAL) @@ -268,12 +268,17 @@ build/symbols_hybrid.vs: build/target_generic/KERNAL_combined.vs # Rules - platform 'Mega 65' specific build/mega65.rom: build/kernal_mega65.rom_0 build/kernal_mega65.rom_1 build/basic_mega65.rom_0 build/chargen.rom - cat build/kernal_mega65.rom_1 > build/mega65.rom - dd if=/dev/zero bs=4096 count=8 of=build/padding1 - cat build/padding1 >> build/mega65.rom - cat build/basic_mega65.rom_0 build/chargen.rom build/chargen.rom build/kernal_mega65.rom_0 >> build/mega65.rom - dd if=/dev/zero bs=4096 count=16 of=build/padding2 - cat build/padding2 >> build/mega65.rom + dd if=/dev/zero bs=8192 count=1 of=build/padding_8k + dd if=/dev/zero bs=8192 count=8 of=build/padding_64k + cat build/padding_8k > build/mega65.rom + cat build/padding_8k >> build/mega65.rom + cat build/kernal_mega65.rom_1 >> build/mega65.rom + cat build/padding_8k >> build/mega65.rom + cat build/padding_8k >> build/mega65.rom + cat build/basic_mega65.rom_0 >> build/mega65.rom + cat build/chargen.rom build/chargen.rom >> build/mega65.rom + cat build/kernal_mega65.rom_0 >> build/mega65.rom + cat build/padding_64k >> build/mega65.rom rm -f build/padding* # Rules - tests diff --git a/c64/kernal/banking/4000.mega65_kernal_1.s b/c64/kernal/banking/4000.mega65_kernal_1.s index fbe3311a..9f29f67c 100644 --- a/c64/kernal/banking/4000.mega65_kernal_1.s +++ b/c64/kernal/banking/4000.mega65_kernal_1.s @@ -1,18 +1,21 @@ +// #LAYOUT# M65 KERNAL_0 #TAKE-FLOAT +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE // // Definitions for communication with Mega65 segment KERNAL_1 // -#if (ROM_LAYOUT_M65 && SEGMENT_KERNAL_0) +#if SEGMENT_KERNAL_0 // Labels for jumps -.label KERNAL_1__TESTROUTINE = $4000 + .label KERNAL_1__TESTROUTINE = $4000 -#elif (ROM_LAYOUT_M65 && SEGMENT_KERNAL_1) +#elif // Jumptable (OpenROMs private!) diff --git a/c64/kernal/banking/mega65_mapping.s b/c64/kernal/banking/mega65_mapping.s index d4f037f1..38672f12 100644 --- a/c64/kernal/banking/mega65_mapping.s +++ b/c64/kernal/banking/mega65_mapping.s @@ -1,9 +1,14 @@ -#if (ROM_LAYOUT_M65 && SEGMENT_KERNAL_0) +// #LAYOUT# M65 KERNAL_0 #TAKE +// #LAYOUT# * * #IGNORE // // ROM mapping routines for Mega65 // +// Available memory maps: +// - NORMAL - nothing mapped in +// - KERNAL_1 - for calling KERNAL_1 segment code + map_NORMAL: @@ -43,9 +48,6 @@ map_KERNAL_1: tay taz - ldx #$42 // XXX map 8KB from 0x20000 to 0x4000 - somehow does not seem to work + ldx #$42 // 0x4000 <- map 8KB from 0x20000 bne map_end - - -#endif // ROM layout diff --git a/c64/kernal/init/fda3.ioinit.s b/c64/kernal/init/fda3.ioinit.s index 758b2dab..f55ac9d3 100644 --- a/c64/kernal/init/fda3.ioinit.s +++ b/c64/kernal/init/fda3.ioinit.s @@ -12,6 +12,12 @@ IOINIT: + // XXX make something useful with this + // + // jsr map_KERNAL_1 + // jsr KERNAL_1__TESTROUTINE + // jsr map_NORMAL + // // First initialize the CPU port, to make sure we have correct memory map // diff --git a/src/build_segment.cc b/src/build_segment.cc index 67c85dbf..8ab7d925 100644 --- a/src/build_segment.cc +++ b/src/build_segment.cc @@ -79,9 +79,14 @@ class SourceFile public: SourceFile(const std::string &fileName, const std::string &dirName); + void preprocess(); + bool preprocessLine(const std::string &line); + bool nameMatch(const std::string &token, const std::string &name); + std::string fileName; std::string dirName; + bool ignore; bool floating; std::vector content; @@ -120,7 +125,7 @@ public: class Solver { public: - Solver(BinningProblem &problem) : problem(problem), logOutput(logFile, std::cout) {} + explicit Solver(BinningProblem &problem) : problem(problem), logOutput(logFile, std::cout) {} void run(); @@ -164,7 +169,7 @@ void parseCommandLine(int argc, char **argv) case 'd': CMD_outDir = optarg; break; case 's': CMD_segName = optarg; break; case 'i': CMD_segInfo = optarg; break; - case 'r': CMD_romLayout = optarg; break; + case 'r': CMD_romLayout = optarg; break; case 'l': CMD_loAddress = strtol(optarg, nullptr ,16); break; case 'h': CMD_hiAddress = strtol(optarg, nullptr ,16); break; default: printUsage(); ERROR(); @@ -196,7 +201,7 @@ void readSourceFiles() // This is a regular file char *tmp1 = strdup(objName.c_str()); - char *tmp2 = strdup(objName.c_str()); + char *tmp2 = strdup(objName.c_str()); std::string dirName = dirname(tmp1); std::string fileName = basename(tmp2); @@ -235,6 +240,11 @@ void readSourceFiles() closedir(dirHandle); } + // Filter-out files marked as ignored + + GLOBAL_sourceFiles.erase(std::remove_if(GLOBAL_sourceFiles.begin(), GLOBAL_sourceFiles.end(), + [](const SourceFile &sourceFile) -> bool { return sourceFile.ignore; }), GLOBAL_sourceFiles.end()); + if (GLOBAL_sourceFiles.empty()) ERROR("no source files found"); // Sort the file list by name, to provide deterministic results @@ -485,7 +495,7 @@ void compileSegment() ", outBin=\"" << CMD_outFile << "\", fill]" << "\n"; outFile << "#define SEGMENT_" << CMD_segName << "\n"; - outFile << "#define ROM_LAYOUT_" << CMD_romLayout << "\n"; + outFile << "#define ROM_LAYOUT_" << CMD_romLayout << "\n"; outFile << ".namespace " << CMD_segName << " {" << "\n\n"; // Write files which only contain definitions (no routines) @@ -557,6 +567,7 @@ int main(int argc, char **argv) SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) : fileName(fileName), dirName(dirName), + ignore(false), floating(false), startAddr(-1), codeLength(-1), @@ -607,6 +618,10 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) startAddr = strtol(fileName.substr(0, 4).c_str(), nullptr ,16); } + // Preprocess the file (apply settings from the content) + + preprocess(); + // Generate KickAss compatible label from the file name label = fileName.substr(0, fileName.length() - 2); @@ -615,6 +630,82 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) std::replace(label.begin(), label.end(), ',', '_'); } +void SourceFile::preprocess() +{ + std::string contentStr(content.begin(), content.end()); + std::istringstream stream(contentStr); + std::string line; + + while (std::getline(stream, line)) + { + if (line.empty()) continue; + std::replace(std::begin(line), std::end(line), '\t', ' '); + if (!preprocessLine(line)) break; + } +} + +bool SourceFile::preprocessLine(const std::string &line) +{ + // Split the line into tokens + + std::list tokens; + + std::istringstream stream(line); + std::string token; + while(std::getline(stream, token, ' ')) + { + if (token.empty()) continue; + tokens.push_back(token); + } + if (tokens.empty()) return true; + + // Now preprocess line using the token list + + auto iter = tokens.begin(); + + // Injest the comment token + + if ((iter++)->compare("//") != 0 || iter == tokens.end()) return true; + + // Check if supported directive + + if ((iter++)->compare("#LAYOUT#") != 0) return true; + + // Check if segment name and rom layout match + + if (iter == tokens.end()) ERROR("syntax error, missing segment name in '#LAYOUT#'"); + if (!nameMatch(*(iter++), CMD_segName)) return true; + + if (iter == tokens.end()) ERROR("syntax error, missing rom layout in '#LAYOUT#'"); + if (!nameMatch(*(iter++), CMD_romLayout)) return true; + + // Retrieve and apply action + + if (iter == tokens.end()) ERROR("syntax error, missing action in '#LAYOUT#'"); + + if (iter->compare("#IGNORE") == 0) + { + ignore = true; + } + else if (iter->compare("#TAKE-FLOAT") == 0) + { + floating = true; + } + else if (iter->compare("#TAKE") != 0) + { + ERROR("syntax error, unsupported action in '#LAYOUT#'"); + } + + // Tell the caller to finish processing the file + + return false; +} + +bool SourceFile::nameMatch(const std::string &token, const std::string &name) +{ + return (token.compare("*") == 0) || (token.compare(name) == 0); +} + // // Class 'BinningProblem' // @@ -630,7 +721,7 @@ BinningProblem::BinningProblem(int loAddress, int hiAddress) gaps[loAddress] = hiAddress - loAddress + 1; - // Initial value of statistics + // Initial value of statistics statSize = gaps[loAddress]; statFree = gaps[loAddress]; @@ -672,7 +763,7 @@ void BinningProblem::addToProblem(SourceFile *routine) // Put the routine into the gap, possibly removing it or splitting into two fixedRoutines[routine->startAddr] = routine; - statFree -= routine->codeLength; + statFree -= routine->codeLength; // Calculate possible new gap after the routine