Refactoring, fixes, lookup tables.

This commit is contained in:
Christian Speckner 2024-07-12 21:52:18 +02:00
parent 0584a25eae
commit c407fedcd2
9 changed files with 289 additions and 140 deletions

View File

@ -20,143 +20,18 @@
#include "System.hxx" #include "System.hxx"
#include "ElfParser.hxx" #include "ElfParser.hxx"
#include "ElfLinker.hxx" #include "ElfLinker.hxx"
#include "ElfEnvironment.hxx"
#include "exception/FatalEmulationError.hxx" #include "exception/FatalEmulationError.hxx"
#include "CartELF.hxx" #include "CartELF.hxx"
#define DUMP_ELF #define DUMP_ELF
using namespace elfEnvironment;
namespace { namespace {
constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384; constexpr size_t TRANSACTION_QUEUE_CAPACITY = 16384;
constexpr uInt8 OVERBLANK_PROGRAM[] = {
0xa0,0x00, // ldy #0
0xa5,0xe0, // lda $e0
// OverblankLoop:
0x85,0x02, // sta WSYNC
0x85,0x2d, // sta AUDV0 (currently using $2d instead to disable audio until fully implemented
0x98, // tya
0x18, // clc
0x6a, // ror
0xaa, // tax
0xb5,0xe0, // lda $e0,x
0x90,0x04, // bcc
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0xc8, // iny
0xc0, 0x1d, // cpy #$1d
0xd0, 0x04, // bne
0xa2, 0x02, // ldx #2
0x86, 0x00, // stx VSYNC
0xc0, 0x20, // cpy #$20
0xd0, 0x04, // bne SkipClearVSync
0xa2, 0x00, // ldx #0
0x86, 0x00, // stx VSYNC
// SkipClearVSync:
0xc0, 0x3f, // cpy #$3f
0xd0, 0xdb, // bne OverblankLoop
// WaitForCart:
0xae, 0xff, 0xff, // ldx $ffff
0xd0, 0xfb, // bne WaitForCart
0x4c, 0x00, 0x10 // jmp $1000
};
constexpr uInt32 ADDR_TEXT_BASE = 0x00100000;
constexpr uInt32 ADDR_DATA_BASE = 0x00200000;
constexpr uInt32 ADDR_ADDR_IDR = 0xf0000000;
constexpr uInt32 ADDR_DATA_IDR = 0xf0000004;
constexpr uInt32 ADDR_DATA_ODR = 0xf0000008;
constexpr uInt32 ADDR_DATA_MODER = 0xf0000010;
constexpr uInt32 VCSLIB_BASE = 0x1001;
constexpr uInt32 ADDR_MEMSET = VCSLIB_BASE;
constexpr uInt32 ADDR_MEMCPY = VCSLIB_BASE + 4;
constexpr uInt32 ADDR_VCS_LDA_FOR_BUS_STUFF2 = VCSLIB_BASE + 8;
constexpr uInt32 ADDR_VCS_LDX_FOR_BUS_STUFF2 = VCSLIB_BASE + 12;
constexpr uInt32 ADDR_VCS_LDY_FOR_BUS_STUFF2 = VCSLIB_BASE + 16;
constexpr uInt32 ADDR_VCS_WRITE3 = VCSLIB_BASE + 20;
constexpr uInt32 ADDR_VCS_JMP3 = VCSLIB_BASE + 24;
constexpr uInt32 ADDR_VCS_NOP2 = VCSLIB_BASE + 28;
constexpr uInt32 ADDR_VCS_NOP2N = VCSLIB_BASE + 32;
constexpr uInt32 ADDR_VCS_WRITE5 = VCSLIB_BASE + 36;
constexpr uInt32 ADDR_VCS_WRITE6 = VCSLIB_BASE + 40;
constexpr uInt32 ADDR_VCS_LDA2 = VCSLIB_BASE + 44;
constexpr uInt32 ADDR_VCS_LDX2 = VCSLIB_BASE + 48;
constexpr uInt32 ADDR_VCS_LDY2 = VCSLIB_BASE + 52;
constexpr uInt32 ADDR_VCS_SAX3 = VCSLIB_BASE + 56;
constexpr uInt32 ADDR_VCS_STA3 = VCSLIB_BASE + 60;
constexpr uInt32 ADDR_VCS_STX3 = VCSLIB_BASE + 64;
constexpr uInt32 ADDR_VCS_STY3 = VCSLIB_BASE + 68;
constexpr uInt32 ADDR_VCS_STA4 = VCSLIB_BASE + 72;
constexpr uInt32 ADDR_VCS_STX4 = VCSLIB_BASE + 76;
constexpr uInt32 ADDR_VCS_STY4 = VCSLIB_BASE + 80;
constexpr uInt32 ADDR_VCS_COPY_OVERBLANK_TO_RIOT_RAM = VCSLIB_BASE + 84;
constexpr uInt32 ADDR_VCS_START_OVERBLANK = VCSLIB_BASE + 88;
constexpr uInt32 ADDR_VCS_END_OVERBLANK = VCSLIB_BASE + 92;
constexpr uInt32 ADDR_VCS_READ4 = VCSLIB_BASE + 96;
constexpr uInt32 ADDR_RANDINT = VCSLIB_BASE + 100;
constexpr uInt32 ADDR_VCS_TXS2 = VCSLIB_BASE + 104;
constexpr uInt32 ADDR_VCS_JSR6 = VCSLIB_BASE + 108;
constexpr uInt32 ADDR_VCS_PHA3 = VCSLIB_BASE + 112;
constexpr uInt32 ADDR_VCS_PHP3 = VCSLIB_BASE + 116;
constexpr uInt32 ADDR_VCS_PLA4 = VCSLIB_BASE + 120;
constexpr uInt32 ADDR_VCS_PLP4 = VCSLIB_BASE + 124;
constexpr uInt32 ADDR_VCS_PLA4_EX = VCSLIB_BASE + 128;
constexpr uInt32 ADDR_VCS_PLP4_EX = VCSLIB_BASE + 132;
constexpr uInt32 ADDR_VCS_JMP_TO_RAM3 = VCSLIB_BASE + 136;
constexpr uInt32 ADDR_VCS_WAIT_FOR_ADDRESS = VCSLIB_BASE + 140;
constexpr uInt32 ADDR_INJECT_DMA_DATA = VCSLIB_BASE + 144;
const vector<ElfLinker::ExternalSymbol> EXTERNAL_SYMBOLS = {
{"ADDR_IDR", ADDR_ADDR_IDR},
{"DATA_IDR", ADDR_DATA_IDR},
{"DATA_ODR", ADDR_DATA_ODR},
{"DATA_MODER", ADDR_DATA_MODER},
{"memset", ADDR_MEMSET},
{"memcpy", ADDR_MEMCPY},
{"vcsLdaForBusStuff2", ADDR_VCS_LDA_FOR_BUS_STUFF2},
{"vcsLdxForBusStuff2", ADDR_VCS_LDX_FOR_BUS_STUFF2},
{"vcsLdyForBusStuff2", ADDR_VCS_LDY_FOR_BUS_STUFF2},
{"vcsWrite3", ADDR_VCS_WRITE3},
{"vcsJmp3", ADDR_VCS_JMP3},
{"vcsNop2", ADDR_VCS_NOP2},
{"vcsNop2n", ADDR_VCS_NOP2N},
{"vcsWrite5", ADDR_VCS_WRITE5},
{"vcsWrite6", ADDR_VCS_WRITE6},
{"vcsLda2", ADDR_VCS_LDA2},
{"vcsLdx2", ADDR_VCS_LDX2},
{"vcsLdy2", ADDR_VCS_LDY2},
{"vcsSax3", ADDR_VCS_SAX3},
{"vcsSta3", ADDR_VCS_STA3},
{"vcsStx3", ADDR_VCS_STX3},
{"vcsSty3", ADDR_VCS_STY3},
{"vcsSta4", ADDR_VCS_STA4},
{"vcsStx4", ADDR_VCS_STX4},
{"vcsSty4", ADDR_VCS_STY4},
{"vcsCopyOverblankToRiotRam", ADDR_VCS_COPY_OVERBLANK_TO_RIOT_RAM},
{"vcsStartOverblank", ADDR_VCS_START_OVERBLANK},
{"vcsEndOverblank", ADDR_VCS_END_OVERBLANK},
{"vcsRead4", ADDR_VCS_READ4},
{"randint", ADDR_RANDINT},
{"vcsTxs2", ADDR_VCS_TXS2},
{"vcsJsr6", ADDR_VCS_JSR6},
{"vcsPha3", ADDR_VCS_PHA3},
{"vcsPhp3", ADDR_VCS_PHP3},
{"vcsPla4", ADDR_VCS_PLA4},
{"vcsPlp4", ADDR_VCS_PLP4},
{"vcsPla4Ex", ADDR_VCS_PLA4_EX},
{"vcsPlp4Ex", ADDR_VCS_PLP4_EX},
{"vcsJmpToRam3", ADDR_VCS_JMP_TO_RAM3},
{"vcsWaitForAddress", ADDR_VCS_WAIT_FOR_ADDRESS},
{"injectDmaData", ADDR_INJECT_DMA_DATA},
{"ReverseByte", 0} // FIXME
};
#ifdef DUMP_ELF #ifdef DUMP_ELF
void dumpElf(const ElfParser& parser) void dumpElf(const ElfParser& parser)
{ {
@ -269,7 +144,7 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
ElfLinker elfLinker(ADDR_TEXT_BASE, ADDR_DATA_BASE, elfParser); ElfLinker elfLinker(ADDR_TEXT_BASE, ADDR_DATA_BASE, elfParser);
try { try {
elfLinker.link(EXTERNAL_SYMBOLS); elfLinker.link(externalSymbols(Palette::ntsc));
} catch (const ElfLinker::ElfLinkError& e) { } catch (const ElfLinker::ElfLinkError& e) {
throw runtime_error("failed to link ELF: " + string(e.what())); throw runtime_error("failed to link ELF: " + string(e.what()));
} }
@ -403,7 +278,7 @@ void CartridgeELF::vcsWrite5(uInt8 zpAddress, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::vcsCopyOverblankToRiotRam() void CartridgeELF::vcsCopyOverblankToRiotRam()
{ {
for (size_t i = 0; i < sizeof(OVERBLANK_PROGRAM); i++) for (size_t i = 0; i < OVERBLANK_PROGRAM_SIZE; i++)
vcsWrite5(0x80 + i, OVERBLANK_PROGRAM[i]); vcsWrite5(0x80 + i, OVERBLANK_PROGRAM[i]);
} }

View File

@ -0,0 +1,152 @@
#include "ElfEnvironment.hxx"
const uInt8 elfEnvironment::OVERBLANK_PROGRAM[] = {
0xa0,0x00, // ldy #0
0xa5,0xe0, // lda $e0
// OverblankLoop:
0x85,0x02, // sta WSYNC
0x85,0x2d, // sta AUDV0 (currently using $2d instead to disable audio until fully implemented
0x98, // tya
0x18, // clc
0x6a, // ror
0xaa, // tax
0xb5,0xe0, // lda $e0,x
0x90,0x04, // bcc
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0xc8, // iny
0xc0, 0x1d, // cpy #$1d
0xd0, 0x04, // bne
0xa2, 0x02, // ldx #2
0x86, 0x00, // stx VSYNC
0xc0, 0x20, // cpy #$20
0xd0, 0x04, // bne SkipClearVSync
0xa2, 0x00, // ldx #0
0x86, 0x00, // stx VSYNC
// SkipClearVSync:
0xc0, 0x3f, // cpy #$3f
0xd0, 0xdb, // bne OverblankLoop
// WaitForCart:
0xae, 0xff, 0xff, // ldx $ffff
0xd0, 0xfb, // bne WaitForCart
0x4c, 0x00, 0x10 // jmp $1000
};
const uInt32 elfEnvironment::OVERBLANK_PROGRAM_SIZE = sizeof(elfEnvironment::OVERBLANK_PROGRAM);
const uInt8 elfEnvironment::LOOKUP_TABLES[3 * 256] = {
// Ntsc2600
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
// Pal2600
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
// ReverseByte
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
vector<ElfLinker::ExternalSymbol> elfEnvironment::externalSymbols(elfEnvironment::Palette palette)
{
static const vector<ElfLinker::ExternalSymbol> EXTERNAL_SYMBOLS_STATIC = {
{"ADDR_IDR", ADDR_ADDR_IDR},
{"DATA_IDR", ADDR_DATA_IDR},
{"DATA_ODR", ADDR_DATA_ODR},
{"DATA_MODER", ADDR_DATA_MODER},
{"memset", ADDR_MEMSET},
{"memcpy", ADDR_MEMCPY},
{"vcsLdaForBusStuff2", ADDR_VCS_LDA_FOR_BUS_STUFF2},
{"vcsLdxForBusStuff2", ADDR_VCS_LDX_FOR_BUS_STUFF2},
{"vcsLdyForBusStuff2", ADDR_VCS_LDY_FOR_BUS_STUFF2},
{"vcsWrite3", ADDR_VCS_WRITE3},
{"vcsJmp3", ADDR_VCS_JMP3},
{"vcsNop2", ADDR_VCS_NOP2},
{"vcsNop2n", ADDR_VCS_NOP2N},
{"vcsWrite5", ADDR_VCS_WRITE5},
{"vcsWrite6", ADDR_VCS_WRITE6},
{"vcsLda2", ADDR_VCS_LDA2},
{"vcsLdx2", ADDR_VCS_LDX2},
{"vcsLdy2", ADDR_VCS_LDY2},
{"vcsSax3", ADDR_VCS_SAX3},
{"vcsSta3", ADDR_VCS_STA3},
{"vcsStx3", ADDR_VCS_STX3},
{"vcsSty3", ADDR_VCS_STY3},
{"vcsSta4", ADDR_VCS_STA4},
{"vcsStx4", ADDR_VCS_STX4},
{"vcsSty4", ADDR_VCS_STY4},
{"vcsCopyOverblankToRiotRam", ADDR_VCS_COPY_OVERBLANK_TO_RIOT_RAM},
{"vcsStartOverblank", ADDR_VCS_START_OVERBLANK},
{"vcsEndOverblank", ADDR_VCS_END_OVERBLANK},
{"vcsRead4", ADDR_VCS_READ4},
{"randint", ADDR_RANDINT},
{"vcsTxs2", ADDR_VCS_TXS2},
{"vcsJsr6", ADDR_VCS_JSR6},
{"vcsPha3", ADDR_VCS_PHA3},
{"vcsPhp3", ADDR_VCS_PHP3},
{"vcsPla4", ADDR_VCS_PLA4},
{"vcsPlp4", ADDR_VCS_PLP4},
{"vcsPla4Ex", ADDR_VCS_PLA4_EX},
{"vcsPlp4Ex", ADDR_VCS_PLP4_EX},
{"vcsJmpToRam3", ADDR_VCS_JMP_TO_RAM3},
{"vcsWaitForAddress", ADDR_VCS_WAIT_FOR_ADDRESS},
{"injectDmaData", ADDR_INJECT_DMA_DATA},
{"ReverseByte", ADDR_TABLE_COLOR_LOOKUP_REVERSE_BYTE}
};
vector<ElfLinker::ExternalSymbol> externalSymbols;
externalSymbols.reserve(EXTERNAL_SYMBOLS_STATIC.size() + 1);
externalSymbols = EXTERNAL_SYMBOLS_STATIC;
externalSymbols.push_back({
"ColorLookup",
palette == Palette::ntsc ? ADDR_TABLE_COLOR_LOOKUP_NTSC : ADDR_TABLE_COLOR_LOOKUP_PAL
});
return externalSymbols;
}

View File

@ -0,0 +1,89 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef ELF_ENVIRONMENT
#define ELF_ENVIRONMENT
#include "bspf.hxx"
#include "ElfLinker.hxx"
namespace elfEnvironment {
constexpr uInt32 ADDR_TEXT_BASE = 0x00100000;
constexpr uInt32 ADDR_DATA_BASE = 0x00200000;
constexpr uInt32 ADDR_TABLES_BASE = 0x00300000;
constexpr uInt32 ADDR_ADDR_IDR = 0xf0000000;
constexpr uInt32 ADDR_DATA_IDR = 0xf0000004;
constexpr uInt32 ADDR_DATA_ODR = 0xf0000008;
constexpr uInt32 ADDR_DATA_MODER = 0xf0000010;
constexpr uInt32 STUB_BASE = 0x1001;
constexpr uInt32 ADDR_MEMSET = STUB_BASE;
constexpr uInt32 ADDR_MEMCPY = STUB_BASE + 4;
constexpr uInt32 ADDR_VCS_LDA_FOR_BUS_STUFF2 = STUB_BASE + 8;
constexpr uInt32 ADDR_VCS_LDX_FOR_BUS_STUFF2 = STUB_BASE + 12;
constexpr uInt32 ADDR_VCS_LDY_FOR_BUS_STUFF2 = STUB_BASE + 16;
constexpr uInt32 ADDR_VCS_WRITE3 = STUB_BASE + 20;
constexpr uInt32 ADDR_VCS_JMP3 = STUB_BASE + 24;
constexpr uInt32 ADDR_VCS_NOP2 = STUB_BASE + 28;
constexpr uInt32 ADDR_VCS_NOP2N = STUB_BASE + 32;
constexpr uInt32 ADDR_VCS_WRITE5 = STUB_BASE + 36;
constexpr uInt32 ADDR_VCS_WRITE6 = STUB_BASE + 40;
constexpr uInt32 ADDR_VCS_LDA2 = STUB_BASE + 44;
constexpr uInt32 ADDR_VCS_LDX2 = STUB_BASE + 48;
constexpr uInt32 ADDR_VCS_LDY2 = STUB_BASE + 52;
constexpr uInt32 ADDR_VCS_SAX3 = STUB_BASE + 56;
constexpr uInt32 ADDR_VCS_STA3 = STUB_BASE + 60;
constexpr uInt32 ADDR_VCS_STX3 = STUB_BASE + 64;
constexpr uInt32 ADDR_VCS_STY3 = STUB_BASE + 68;
constexpr uInt32 ADDR_VCS_STA4 = STUB_BASE + 72;
constexpr uInt32 ADDR_VCS_STX4 = STUB_BASE + 76;
constexpr uInt32 ADDR_VCS_STY4 = STUB_BASE + 80;
constexpr uInt32 ADDR_VCS_COPY_OVERBLANK_TO_RIOT_RAM = STUB_BASE + 84;
constexpr uInt32 ADDR_VCS_START_OVERBLANK = STUB_BASE + 88;
constexpr uInt32 ADDR_VCS_END_OVERBLANK = STUB_BASE + 92;
constexpr uInt32 ADDR_VCS_READ4 = STUB_BASE + 96;
constexpr uInt32 ADDR_RANDINT = STUB_BASE + 100;
constexpr uInt32 ADDR_VCS_TXS2 = STUB_BASE + 104;
constexpr uInt32 ADDR_VCS_JSR6 = STUB_BASE + 108;
constexpr uInt32 ADDR_VCS_PHA3 = STUB_BASE + 112;
constexpr uInt32 ADDR_VCS_PHP3 = STUB_BASE + 116;
constexpr uInt32 ADDR_VCS_PLA4 = STUB_BASE + 120;
constexpr uInt32 ADDR_VCS_PLP4 = STUB_BASE + 124;
constexpr uInt32 ADDR_VCS_PLA4_EX = STUB_BASE + 128;
constexpr uInt32 ADDR_VCS_PLP4_EX = STUB_BASE + 132;
constexpr uInt32 ADDR_VCS_JMP_TO_RAM3 = STUB_BASE + 136;
constexpr uInt32 ADDR_VCS_WAIT_FOR_ADDRESS = STUB_BASE + 140;
constexpr uInt32 ADDR_INJECT_DMA_DATA = STUB_BASE + 144;
constexpr uInt32 ADDR_TABLE_COLOR_LOOKUP_NTSC = ADDR_TABLES_BASE;
constexpr uInt32 ADDR_TABLE_COLOR_LOOKUP_PAL = ADDR_TABLES_BASE + 256;
constexpr uInt32 ADDR_TABLE_COLOR_LOOKUP_REVERSE_BYTE = ADDR_TABLES_BASE + 512;
extern const uInt8 LOOKUP_TABLES[3 * 256];
extern const uInt8 OVERBLANK_PROGRAM[];
extern const uInt32 OVERBLANK_PROGRAM_SIZE;
enum class Palette: uInt8 {pal, ntsc};
vector<ElfLinker::ExternalSymbol> externalSymbols(Palette palette);
}
#endif // ELF_ENVIRONMENT

View File

@ -18,6 +18,7 @@
#include <unordered_map> #include <unordered_map>
#include "ElfUtil.hxx" #include "ElfUtil.hxx"
#include "Logger.hxx"
#include "ElfLinker.hxx" #include "ElfLinker.hxx"
@ -25,6 +26,13 @@ ElfLinker::ElfLinker(uInt32 textBase, uInt32 dataBase, const ElfParser& parser)
: myTextBase(textBase), myDataBase(dataBase), myParser(parser) : myTextBase(textBase), myDataBase(dataBase), myParser(parser)
{} {}
ElfLinker& ElfLinker::setUndefinedSymbolDefault(uInt32 defaultValue)
{
undefinedSymbolDefault = defaultValue;
return *this;
}
void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols) void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
{ {
myTextSize = myDataSize = 0; myTextSize = myDataSize = 0;
@ -104,14 +112,17 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
const auto& symbol = symbols[i]; const auto& symbol = symbols[i];
if (symbol.section == ElfParser::SHN_ABS) { if (symbol.section == ElfParser::SHN_ABS) {
myRelocatedSymbols[i] = {std::nullopt, symbol.value}; myRelocatedSymbols[i] = {std::nullopt, symbol.value, false};
continue; continue;
} }
if (symbol.section == ElfParser::SHN_UND) { if (symbol.section == ElfParser::SHN_UND) {
if (externalSymbolLookup.contains(symbol.name)) if (externalSymbolLookup.contains(symbol.name))
myRelocatedSymbols[i] = {std::nullopt, externalSymbolLookup[symbol.name]->value}; myRelocatedSymbols[i] = {std::nullopt, externalSymbolLookup[symbol.name]->value, false};
else if (undefinedSymbolDefault)
myRelocatedSymbols[i] = {std::nullopt, *undefinedSymbolDefault, true};
continue; continue;
} }
@ -123,7 +134,7 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
value += relocatedSection->offset; value += relocatedSection->offset;
if (symbol.type != ElfParser::STT_SECTION) value += symbol.value; if (symbol.type != ElfParser::STT_SECTION) value += symbol.value;
myRelocatedSymbols[i] = {relocatedSection->segment, value}; myRelocatedSymbols[i] = {relocatedSection->segment, value, false};
} }
// apply relocations // apply relocations
@ -209,10 +220,18 @@ void ElfLinker::applyRelocation(const ElfParser::Relocation& relocation, size_t
const auto& symbol = myParser.getSymbols()[relocation.symbol]; const auto& symbol = myParser.getSymbols()[relocation.symbol];
const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol]; const auto& relocatedSymbol = myRelocatedSymbols[relocation.symbol];
if (!relocatedSymbol) if (!relocatedSymbol) ElfLinkError::raise(
ElfLinkError::raise( "unable to relocate " + symbol.name + " in " + targetSection.name + ": symbol could not be relocated"
"unable to relocate " + symbol.name + " in " + targetSection.name + ": symbol could not be relocated" );
);
if (relocatedSymbol->undefined) {
stringstream s;
s << "unable to resolve symbol " << relocation.symbolName << " - using default 0x"
<< std::hex << std::setw(8) << std::setfill('0') << relocatedSymbol->value;
Logger::error(s.str());
}
if (relocation.offset + 4 > targetSection.size) if (relocation.offset + 4 > targetSection.size)
ElfLinkError::raise( ElfLinkError::raise(

View File

@ -67,6 +67,7 @@ class ElfLinker {
struct RelocatedSymbol { struct RelocatedSymbol {
optional<SegmentType> segment; optional<SegmentType> segment;
uInt32 value; uInt32 value;
bool undefined;
}; };
struct ExternalSymbol { struct ExternalSymbol {
@ -77,6 +78,7 @@ class ElfLinker {
public: public:
ElfLinker(uInt32 textBase, uInt32 dataBase, const ElfParser& parser); ElfLinker(uInt32 textBase, uInt32 dataBase, const ElfParser& parser);
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
void link(const vector<ExternalSymbol>& externalSymbols); void link(const vector<ExternalSymbol>& externalSymbols);
uInt32 getTextBase() const; uInt32 getTextBase() const;
@ -102,6 +104,8 @@ class ElfLinker {
void write32(uInt8* address, uInt32 value); void write32(uInt8* address, uInt32 value);
private: private:
std::optional<uInt32> undefinedSymbolDefault;
const uInt32 myTextBase{0}; const uInt32 myTextBase{0};
const uInt32 myDataBase{0}; const uInt32 myDataBase{0};
const ElfParser& myParser; const ElfParser& myParser;

View File

@ -181,8 +181,9 @@ ElfParser::Section ElfParser::readSection(uInt32 offset) const {
section.info = read32(offset + 0x1c); section.info = read32(offset + 0x1c);
section.align = read32(offset + 0x20); section.align = read32(offset + 0x20);
if (section.offset + section.size >= mySize) if (section.offset + section.size >= mySize && section.type != SHT_NOBITS)
ElfParseError::raise("section exceeds bounds"); ElfParseError::raise("section exceeds bounds");
} catch (const ElfParseError &e) { } catch (const ElfParseError &e) {
ElfParseError::raise("failed to read section: " + string(e.what())); ElfParseError::raise("failed to read section: " + string(e.what()));
} }

View File

@ -3,7 +3,8 @@ MODULE := src/emucore/elf
MODULE_OBJS = \ MODULE_OBJS = \
src/emucore/elf/ElfParser.o \ src/emucore/elf/ElfParser.o \
src/emucore/elf/ElfLinker.o \ src/emucore/elf/ElfLinker.o \
src/emucore/elf/ElfUtil.o src/emucore/elf/ElfUtil.o \
src/emucore/elf/ElfEnvironment.o
MODULE_TEST_OBJS = \ MODULE_TEST_OBJS = \
src/emucore/elf/ElfUtil.o \ src/emucore/elf/ElfUtil.o \

View File

@ -694,6 +694,7 @@
<ClCompile Include="..\..\emucore\elf\ElfParser.cxx" /> <ClCompile Include="..\..\emucore\elf\ElfParser.cxx" />
<ClCompile Include="..\..\emucore\elf\ElfLinker.cxx" /> <ClCompile Include="..\..\emucore\elf\ElfLinker.cxx" />
<ClCompile Include="..\..\emucore\elf\ElfUtil.cxx" /> <ClCompile Include="..\..\emucore\elf\ElfUtil.cxx" />
<ClCompile Include="..\..\emucore\elf\ElfEnvironment.cxx" />
<ClCompile Include="..\..\emucore\EmulationTiming.cxx" /> <ClCompile Include="..\..\emucore\EmulationTiming.cxx" />
<ClCompile Include="..\..\emucore\EmulationWorker.cxx" /> <ClCompile Include="..\..\emucore\EmulationWorker.cxx" />
<ClCompile Include="..\..\emucore\FBSurface.cxx" /> <ClCompile Include="..\..\emucore\FBSurface.cxx" />
@ -1667,6 +1668,7 @@
<ClInclude Include="..\..\emucore\elf\ElfParser.hxx" /> <ClInclude Include="..\..\emucore\elf\ElfParser.hxx" />
<ClInclude Include="..\..\emucore\elf\ElfLinker.hxx" /> <ClInclude Include="..\..\emucore\elf\ElfLinker.hxx" />
<ClInclude Include="..\..\emucore\elf\ElfUtil.hxx" /> <ClInclude Include="..\..\emucore\elf\ElfUtil.hxx" />
<ClInclude Include="..\..\emucore\elf\ElfEnvironment.hxx" />
<ClInclude Include="..\..\emucore\EmulationTiming.hxx" /> <ClInclude Include="..\..\emucore\EmulationTiming.hxx" />
<ClInclude Include="..\..\emucore\EmulationWorker.hxx" /> <ClInclude Include="..\..\emucore\EmulationWorker.hxx" />
<ClInclude Include="..\..\emucore\EventHandlerConstants.hxx" /> <ClInclude Include="..\..\emucore\EventHandlerConstants.hxx" />

View File

@ -1254,6 +1254,9 @@
<ClCompile Include="..\..\emucore\elf\ElfUtil.cxx"> <ClCompile Include="..\..\emucore\elf\ElfUtil.cxx">
<Filter>Source Files\emucore\elf</Filter> <Filter>Source Files\emucore\elf</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\emucore\elf\ElfEnvironment.cxx">
<Filter>Source Files\emucore\elf</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\emucore\AtariVox.hxx"> <ClInclude Include="..\..\emucore\AtariVox.hxx">
@ -2537,6 +2540,9 @@
<ClInclude Include="..\..\emucore\elf\ElfUtil.hxx"> <ClInclude Include="..\..\emucore\elf\ElfUtil.hxx">
<Filter>Header Files\emucore\elf</Filter> <Filter>Header Files\emucore\elf</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\emucore\elf\ElfEnvironment.hxx">
<Filter>Header Files\emucore\elf</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="stella.ico"> <None Include="stella.ico">