diff options
author | Oxore <oxore@protonmail.com> | 2023-06-09 00:41:05 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-06-09 00:41:05 +0300 |
commit | a8beae02428f4c7762c3621b4a6d23a498b7d394 (patch) | |
tree | e8f0bcc67aa62aeb1d74a462119923e615ea3031 | |
parent | 0c6c5803588a06160fbb55dd4228e94453df89ff (diff) |
Impl VDP register bits tracing
-rw-r--r-- | vdp.cpp | 119 | ||||
-rw-r--r-- | vdp.hpp | 216 |
2 files changed, 221 insertions, 114 deletions
@@ -131,6 +131,117 @@ static constexpr uint16_t kScrollSpeedMask = BitsCountToMask(10); // Each pixel has 4 bit depth color static constexpr uint16_t kPixelColorMask = BitsCountToMask(kBitsPerPixel); +static const char* reg_mode_set_1_bits[8] = { + "Unused(7)", + "Unused(6)", + "Unused(5)", + "HInt(4)", + "Unused(3)", + "AllBitsFromColor(2)", + "HVCounter(1)", + "Unused(0)", +}; + +static const char* reg_mode_set_2_bits[8] = { + "Unused(7)", + "Display(6)", + "VInt(5)", + "DMA(4)", + "V30Cell(3)", + "Unused(2)", + "Unused(1)", + "Unused(0)", +}; + +static const char* reg_mode_set_3_bits[8] = { + "Unused(7)", + "Unused(6)", + "Unused(5)", + "Unused(4)", + "ExtInt(3)", + "2CellVScroll(2)", + "HScrollHi(1)", + "HScrollLo(0)", +}; + +static const char* reg_mode_set_4_bits[8] = { + "H40CellHi(7)", + "Unused(6)", + "Unused(5)", + "Unused(4)", + "Shadow(3)", + "InterlaceHi(2)", + "InterlaceLo(1)", + "H40CellLo(0)", +}; + +static void TraceRegBits(FILE* s, const char* bits_desc[8], const uint8_t val) +{ + fprintf(s, "("); + bool separator{}; + for (size_t i = 0; i < 8; i++) { + if (val & (1 << (7 - i))) { + if (separator) { + fprintf(s, " | "); + separator = false; + } + fprintf(s, bits_desc[i]); + separator = true; + } + } + fprintf(s, ")"); +} + +static void TraceRegWrite(FILE* const s, const uint8_t reg, const uint8_t val) +{ + const auto reg_id = static_cast<VDP::RegID>(reg); + fprintf(s, ": reg 0x%02x(%s) = 0x%02x", reg, VDP::RegIDToString(reg_id), val); + switch (reg_id) { + case VDP::RegID::kModeSet1: + return TraceRegBits(s, reg_mode_set_1_bits, val); + case VDP::RegID::kModeSet2: + return TraceRegBits(s, reg_mode_set_2_bits, val); + case VDP::RegID::kScrollAAddress: + break; + case VDP::RegID::kWindowAddress: + break; + case VDP::RegID::kScrollBAddress: + break; + case VDP::RegID::kSpritesTableAddress: + break; + case VDP::RegID::kBackgroundColor: + break; + case VDP::RegID::kHint: + break; + case VDP::RegID::kModeSet3: + return TraceRegBits(s, reg_mode_set_3_bits, val); + case VDP::RegID::kModeSet4: + return TraceRegBits(s, reg_mode_set_4_bits, val); + case VDP::RegID::kHScrollTableAddress: + break; + case VDP::RegID::kAutoIncrement: + break; + case VDP::RegID::kScrollSize: + break; + case VDP::RegID::kWindowHorizontalPosition: + break; + case VDP::RegID::kWindowVertialPosition: + break; + case VDP::RegID::kDMALengthCounterLow: + break; + case VDP::RegID::kDMALengthCounterHigh: + break; + case VDP::RegID::kDMASourceAddressLow: + break; + case VDP::RegID::kDMASourceAddressMid: + break; + case VDP::RegID::kDMASourceAddressHigh: + break; + case VDP::RegID::kRegistersCount: + break; + } +} + uint32_t VDP::Read(const uint32_t offset, const enum bitness bitness) { uint32_t ret{}; @@ -634,11 +745,7 @@ void VDP::writeControl(const uint16_t value) const uint8_t reg_num = (value >> 8) & 0x1f; const uint8_t reg_val = value & 0xff; if (DEBUG_TRACE_VDP_ACCESS) { - printf( - ": reg 0x%02x(%s) = 0x%02x", - reg_num, - regIDToString(static_cast<RegID>(reg_num)), - reg_val); + TraceRegWrite(stdout, reg_num, reg_val); } _reg[reg_num] = reg_val; // TODO print warnings of all invalid values or writes that ignore a mask @@ -838,7 +945,7 @@ const char* VDP::addressModeToString(const uint8_t address_mode) return "Unknown"; } -const char* VDP::regIDToString(const RegID reg_id) +const char* VDP::RegIDToString(const RegID reg_id) { switch (reg_id) { case RegID::kModeSet1: @@ -22,121 +22,121 @@ struct SpriteAttributeEntry { }; class VDP { - public: - constexpr VDP(const uint32_t base_address_a = VDP_START): base_address(base_address_a) {} - uint32_t Read(uint32_t offset, enum bitness); - void Write(uint32_t offset, enum bitness, uint32_t value); - bool Scanline(); // Returns true if display disabled or vblank happened - void Reset(); - constexpr const uint32_t* GetRenderedBuffer() const { return _rendered_buffer; } +public: + enum class RegID: size_t { + kModeSet1 = 0, + kModeSet2 = 1, + kScrollAAddress = 2, + kWindowAddress = 3, + kScrollBAddress = 4, + kSpritesTableAddress = 5, + kBackgroundColor = 7, + kHint = 10, + kModeSet3 = 11, + kModeSet4 = 12, + kHScrollTableAddress = 13, + kAutoIncrement = 15, + kScrollSize = 16, + kWindowHorizontalPosition = 17, + kWindowVertialPosition = 18, + kDMALengthCounterLow = 19, + kDMALengthCounterHigh = 20, + kDMASourceAddressLow = 21, + kDMASourceAddressMid = 22, + kDMASourceAddressHigh = 23, + kRegistersCount, ///< Keep it last + }; - const uint32_t base_address; + constexpr VDP(const uint32_t base_address_a = VDP_START): base_address(base_address_a) {} + uint32_t Read(uint32_t offset, enum bitness); + void Write(uint32_t offset, enum bitness, uint32_t value); + bool Scanline(); // Returns true if display disabled or vblank happened + void Reset(); + constexpr const uint32_t* GetRenderedBuffer() const { return _rendered_buffer; } + static const char* RegIDToString(RegID); - static constexpr size_t kRenderHeight = 224; - static constexpr size_t kRenderWidth = 320; - static constexpr size_t render_buffer_size = kRenderWidth * kRenderHeight * - sizeof(*reinterpret_cast<VDP*>(4)->GetRenderedBuffer()); + static constexpr size_t kRenderHeight = 224; + static constexpr size_t kRenderWidth = 320; + static constexpr size_t render_buffer_size = kRenderWidth * kRenderHeight * + sizeof(*reinterpret_cast<VDP*>(4)->GetRenderedBuffer()); - private: - struct StatusRegister { - bool fifo_not_empty{}; - bool fifo_full{}; - bool v_irq{}; - bool sprites_overflow{}; - bool sprites_collision{}; - bool odd_frame{}; - bool vblank{}; - bool hblank{}; - bool dma_busy{}; - bool pal_mode{}; - }; + const uint32_t base_address; - enum class AddressMode: uint8_t { - kVRAMWrite = 1, - kCRAMWrite = 3, - kVSRAMWrite = 5, - kVRAMRead = 0, - kCRAMRead = 8, - kVSRAMRead = 4, - }; +private: + struct StatusRegister { + bool fifo_not_empty{}; + bool fifo_full{}; + bool v_irq{}; + bool sprites_overflow{}; + bool sprites_collision{}; + bool odd_frame{}; + bool vblank{}; + bool hblank{}; + bool dma_busy{}; + bool pal_mode{}; + }; - enum class RegID: size_t { - kModeSet1 = 0, - kModeSet2 = 1, - kScrollAAddress = 2, - kWindowAddress = 3, - kScrollBAddress = 4, - kSpritesTableAddress = 5, - kBackgroundColor = 7, - kHint = 10, - kModeSet3 = 11, - kModeSet4 = 12, - kHScrollTableAddress = 13, - kAutoIncrement = 15, - kScrollSize = 16, - kWindowHorizontalPosition = 17, - kWindowVertialPosition = 18, - kDMALengthCounterLow = 19, - kDMALengthCounterHigh = 20, - kDMASourceAddressLow = 21, - kDMASourceAddressMid = 22, - kDMASourceAddressHigh = 23, - kRegistersCount, ///< Keep it last - }; + enum class AddressMode: uint8_t { + kVRAMWrite = 1, + kCRAMWrite = 3, + kVSRAMWrite = 5, + kVRAMRead = 0, + kCRAMRead = 8, + kVSRAMRead = 4, + }; - void renderScrollLine( - size_t line_index, - uint16_t plane_addr, - uint16_t hscroll_table_addr, - size_t plane_index, - size_t hcell_count, - size_t vcell_count); - void renderScrollALine(size_t line_index, size_t hcell_count, size_t vcell_count); - void renderScrollBLine(size_t line_index, size_t hcell_count, size_t vcell_count); - void renderSpritesLine(size_t line_index); - void renderSpriteOnTheLine(SpriteAttributeEntry, size_t line_index); - void writeData(uint8_t address_mode, uint16_t address, uint16_t value); - void writeControl(uint16_t value); - uint16_t readData(uint8_t address_mode, uint16_t address); - uint16_t readStatusRegister() const; - uint8_t* baseFromAddressMode(uint8_t address_mode); - const char* addressModeToString(uint8_t address_mode); - const char* regIDToString(RegID); + void renderScrollLine( + size_t line_index, + uint16_t plane_addr, + uint16_t hscroll_table_addr, + size_t plane_index, + size_t hcell_count, + size_t vcell_count); + void renderScrollALine(size_t line_index, size_t hcell_count, size_t vcell_count); + void renderScrollBLine(size_t line_index, size_t hcell_count, size_t vcell_count); + void renderSpritesLine(size_t line_index); + void renderSpriteOnTheLine(SpriteAttributeEntry, size_t line_index); + void writeData(uint8_t address_mode, uint16_t address, uint16_t value); + void writeControl(uint16_t value); + uint16_t readData(uint8_t address_mode, uint16_t address); + uint16_t readStatusRegister() const; + uint8_t* baseFromAddressMode(uint8_t address_mode); + const char* addressModeToString(uint8_t address_mode); - static void runDMAMemoryToVRAM( - uint8_t* base, - uint32_t source_address, - uint16_t destination_address, - uint16_t transfer_size, - uint8_t increment); - static void runDMAVRAMFill( - uint8_t* base, - uint16_t destination_address, - uint16_t transfer_size, - uint8_t increment, - uint16_t filler); - static void runDMAVRAMCopy(uint8_t* base); + static void runDMAMemoryToVRAM( + uint8_t* base, + uint32_t source_address, + uint16_t destination_address, + uint16_t transfer_size, + uint8_t increment); + static void runDMAVRAMFill( + uint8_t* base, + uint16_t destination_address, + uint16_t transfer_size, + uint8_t increment, + uint16_t filler); + static void runDMAVRAMCopy(uint8_t* base); - static constexpr size_t kRegistersCount = static_cast<size_t>(RegID::kRegistersCount); - static constexpr size_t kVRAMSize = 64*1024; - static constexpr size_t kCRAMSize = 64*2; - static constexpr size_t kVSRAMSize = 40*2; - static constexpr uint16_t kLinesPerScreenNTSC = 262; - static constexpr uint16_t kLinesPerScreenPAL = 312; + static constexpr size_t kRegistersCount = static_cast<size_t>(RegID::kRegistersCount); + static constexpr size_t kVRAMSize = 64*1024; + static constexpr size_t kCRAMSize = 64*2; + static constexpr size_t kVSRAMSize = 40*2; + static constexpr uint16_t kLinesPerScreenNTSC = 262; + static constexpr uint16_t kLinesPerScreenPAL = 312; - StatusRegister _status{}; - bool _control_write_second_word{}; - // DMA Fill is ready to kick in, waiting for filler set to data port - bool _dma_ready{}; - uint16_t _lines_counter{}; - // TODO: Make _address_mode of type AddressMode somehow and all private - // methods using it should be accepting AddressMode instead of uint8_t. - uint8_t _address_mode{}; - uint16_t _address{}; - uint8_t _reg[kRegistersCount]{}; - uint8_t _vram[kVRAMSize]{}; - uint8_t _cram[kCRAMSize]{}; - uint8_t _vsram[kVSRAMSize]{}; - uint32_t _rendered_buffer[kLinesPerScreenNTSC * kRenderWidth]{}; - bool _unclosed_sprites_list{}; + StatusRegister _status{}; + bool _control_write_second_word{}; + // DMA Fill is ready to kick in, waiting for filler set to data port + bool _dma_ready{}; + uint16_t _lines_counter{}; + // TODO: Make _address_mode of type AddressMode somehow and all private + // methods using it should be accepting AddressMode instead of uint8_t. + uint8_t _address_mode{}; + uint16_t _address{}; + uint8_t _reg[kRegistersCount]{}; + uint8_t _vram[kVRAMSize]{}; + uint8_t _cram[kCRAMSize]{}; + uint8_t _vsram[kVSRAMSize]{}; + uint32_t _rendered_buffer[kLinesPerScreenNTSC * kRenderWidth]{}; + bool _unclosed_sprites_list{}; }; |