From 35f20a16b8bb85677f3ff52e2c5d99bddb4899a6 Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 20 May 2026 17:55:07 +0200 Subject: [PATCH] i should implement DSP DMA... --- CMakeLists.txt | 3 +- core/broadway.cpp | 40 ++++++++++- core/broadway.hpp | 13 +++- core/broadway/instructions.cpp | 124 ++++++++++++++++++++++++++++++-- core/broadway/mmio/ai.cpp | 10 +-- core/broadway/mmio/ai.hpp | 4 +- core/broadway/mmio/dsp.cpp | 125 ++++++++++++++++++++++++++++++++- core/broadway/mmio/dsp.hpp | 17 ++++- core/broadway/mmio/si.cpp | 46 ++++++++++++ core/broadway/mmio/si.hpp | 75 ++++++++++++++++++++ core/broadway/mmio/vi.cpp | 55 +++++++++++++++ core/broadway/mmio/vi.hpp | 5 +- core/mem.cpp | 2 +- core/mem.hpp | 4 +- main.cpp | 2 +- 15 files changed, 500 insertions(+), 25 deletions(-) create mode 100644 core/broadway/mmio/si.cpp create mode 100644 core/broadway/mmio/si.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 08424c1..9899385 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(weee main.cpp core/mem.cpp core/loaders/elf.cpp core/broadway/mmio/mi.cpp core/broadway/mmio/dsp.cpp core/broadway/mmio/ai.cpp - core/broadway/mmio/exi.cpp) + core/broadway/mmio/exi.cpp + core/broadway/mmio/si.cpp) target_link_libraries(weee PUBLIC SDL3::SDL3 capstone) target_include_directories(weee PUBLIC core) \ No newline at end of file diff --git a/core/broadway.cpp b/core/broadway.cpp index be628b3..316f5b0 100644 --- a/core/broadway.cpp +++ b/core/broadway.cpp @@ -16,9 +16,10 @@ broadway::broadway() { void broadway::set_pc(ircolib::u32 value) { pc = value; } void broadway::run(mem &mem) { - for (int i = 0; i < 12150000; i++) { - // std::println("pc: 0x{:08X}", pc); - execute(fetch(mem), mem); + std::println("pc: 0x{:08X}", pc); + for (int i = 0; i < 1000000; i++) { + ircolib::u32 instr = fetch(mem); + execute(instr, mem); } } @@ -58,6 +59,12 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x000: cmp(instr); break; + case 0x008: + subfc(instr); + break; + case 0x00A: + addc(instr); + break; case 0x013: mfcr(instr); break; @@ -76,6 +83,12 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x053: mfmsr(instr); break; + case 0x088: + subfe(instr); + break; + case 0x08A: + adde(instr); + break; case 0x090: mtcrf(instr); break; @@ -85,12 +98,21 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { case 0x097: stwx(instr, mem); break; + case 0x0CA: + addze(instr); + break; case 0x0D2: ircolib::warn("broadway TODO mtsr (pc 0x{:08X})", pc - 4); break; case 0x0EB: mullw(instr); break; + case 0x117: + lhzx(instr, mem); + break; + case 0x173: + mftb(instr); + break; case 0x1BC: or (instr); break; @@ -109,6 +131,9 @@ void broadway::decode_special2(ircolib::u32 instr, mem &mem) { break; case 0x256: // sync break; + case 0x318: + sraw(instr); + break; default: std::println("broadway unknown special2 {} (0x{:04X}) (pc 0x{:08X})", secondary, secondary, pc - 4); std::println("disassembly:"); @@ -142,6 +167,9 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 7: mulli(instr); break; + case 8: + subfic(instr); + break; case 10: cmpli(instr); break; @@ -181,6 +209,9 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 25: oris(instr); break; + case 26: + xori(instr); + break; case 28: andi(instr); break; @@ -217,6 +248,9 @@ void broadway::execute(ircolib::u32 instr, mem &mem) { case 44: sth(instr, mem); break; + case 45: + sthu(instr, mem); + break; case 50: lfd(instr, mem); break; diff --git a/core/broadway.hpp b/core/broadway.hpp index 00ad1cf..01141d8 100644 --- a/core/broadway.hpp +++ b/core/broadway.hpp @@ -17,7 +17,7 @@ struct broadway { void execute(ircolib::u32, mem &); bool disasm_available = true; - ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0 = 0, fpscr = 0, msr = 0; + ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0 = 0, fpscr = 0, msr = 0, tbl = 0, tbu = 0; union { struct { unsigned bytecount : 7; @@ -66,6 +66,9 @@ struct broadway { void andis(ircolib::u32); void and(ircolib::u32); void add(ircolib::u32); + void addc(ircolib::u32); + void adde(ircolib::u32); + void addze(ircolib::u32); void addis(ircolib::u32); void addi(ircolib::u32); void addic(ircolib::u32); @@ -79,6 +82,7 @@ struct broadway { void stw(ircolib::u32, mem &); void stb(ircolib::u32, mem &); void stwu(ircolib::u32, mem &); + void sthu(ircolib::u32, mem &); void stwx(ircolib::u32, mem &); void stbu(ircolib::u32, mem &); void sth(ircolib::u32, mem &); @@ -86,6 +90,7 @@ struct broadway { void lwz(ircolib::u32, mem &); void lwzx(ircolib::u32, mem &); void lhz(ircolib::u32, mem &); + void lhzx(ircolib::u32, mem &); void lfd(ircolib::u32, mem &); void bclrx(ircolib::u32); void cmpi(ircolib::u32); @@ -106,8 +111,14 @@ struct broadway { void mulli(ircolib::u32); void nand(ircolib::u32); void subf(ircolib::u32); + void subfc(ircolib::u32); + void subfic(ircolib::u32); + void subfe(ircolib::u32); void or (ircolib::u32); + void xori(ircolib::u32); void divwu(ircolib::u32); + void mftb(ircolib::u32); + void sraw(ircolib::u32); inline void cr0_update(bool condition, ircolib::s32 result) { if (condition) { diff --git a/core/broadway/instructions.cpp b/core/broadway/instructions.cpp index c1e42bd..4d75c12 100644 --- a/core/broadway/instructions.cpp +++ b/core/broadway/instructions.cpp @@ -8,6 +8,31 @@ void broadway::add(ircolib::u32 instr) { cr0_update(instr & 1, gpr[utils::RD(instr)]); } +void broadway::addc(ircolib::u32 instr) { + ircolib::u32 sum; + bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum); + cr0_update(instr & 1, sum); + xer.ca = carry; + gpr[utils::RD(instr)] = sum; +} + +void broadway::adde(ircolib::u32 instr) { + ircolib::u32 sum; + bool c0 = __builtin_add_overflow(gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum); + bool c1 = __builtin_add_overflow(sum, xer.ca, &sum); + cr0_update(instr & 1, sum); + xer.ca = c0 | c1; + gpr[utils::RD(instr)] = sum; +} + +void broadway::addze(ircolib::u32 instr) { + ircolib::u32 sum; + bool c1 = __builtin_add_overflow(gpr[utils::RA(instr)], xer.ca, &sum); + cr0_update(instr & 1, sum); + xer.ca = c1; + gpr[utils::RD(instr)] = sum; +} + void broadway::addi(ircolib::u32 instr) { if (utils::RA(instr) == 0) { // li gpr[utils::RD(instr)] = ircolib::s32(utils::SIMM(instr)); @@ -17,13 +42,19 @@ void broadway::addi(ircolib::u32 instr) { gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); } -void broadway::addicr(ircolib::u32 instr) { - gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); - cr0_update(true, gpr[utils::RD(instr)]); +void broadway::addic(ircolib::u32 instr) { + ircolib::u32 sum; + bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum); + gpr[utils::RD(instr)] = sum; + xer.ca = carry; } -void broadway::addic(ircolib::u32 instr) { - gpr[utils::RD(instr)] = gpr[utils::RA(instr)] + (ircolib::s32(utils::SIMM(instr))); +void broadway::addicr(ircolib::u32 instr) { + ircolib::u32 sum; + bool carry = __builtin_add_overflow(gpr[utils::RA(instr)], ircolib::s32(utils::SIMM(instr)), &sum); + cr0_update(true, sum); + gpr[utils::RD(instr)] = sum; + xer.ca = carry; } void broadway::addis(ircolib::u32 instr) { @@ -167,6 +198,22 @@ void broadway::stwu(ircolib::u32 instr, mem &mem) { }); } +void broadway::sthu(ircolib::u32 instr, mem &mem) { + if (utils::RA(instr) == 0) + ircolib::panic("broadway::sthu with ra == 0"); + + const ircolib::u32 EA = ircolib::s32(gpr[utils::RA(instr)]) + utils::SIMM(instr); + auto _ = mem.write16(EA, gpr[utils::RS(instr)]) + .and_then([&] { + gpr[utils::RA(instr)] = EA; + return std::expected(); + }) + .or_else([&](std::string e) { + ircolib::panic("sthu broadway write failed. Reason: {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }); +} + void broadway::stbu(ircolib::u32 instr, mem &mem) { if (utils::RA(instr) == 0) ircolib::panic("broadway::stbu with ra == 0"); @@ -288,6 +335,22 @@ void broadway::lhz(ircolib::u32 instr, mem &mem) { .value(); } +void broadway::lhzx(ircolib::u32 instr, mem &mem) { + ircolib::u32 b = gpr[utils::RA(instr)]; + if (utils::RA(instr) == 0) + b = 0; + + ircolib::u32 ea = ircolib::s32(b) + gpr[utils::RB(instr)]; + + gpr[utils::RD(instr)] = mem.read16(ea) + .and_then([&](ircolib::u32 val) { return std::expected(val); }) + .or_else([&](std::string e) { + ircolib::panic("lhzx broadway read failed. Reason {} (pc: 0x{:08X})", e, pc - 4); + return std::expected(); + }) + .value(); +} + void broadway::lbz(ircolib::u32 instr, mem &mem) { ircolib::u32 b = gpr[utils::RA(instr)]; if (utils::RA(instr) == 0) @@ -505,11 +568,39 @@ void broadway::subf(ircolib::u32 instr) { cr0_update(instr & 1, gpr[utils::RD(instr)]); } +void broadway::subfc(ircolib::u32 instr) { + ircolib::u32 sum; + bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum); + bool c1 = __builtin_add_overflow(sum, gpr[utils::RB(instr)], &sum); + cr0_update(instr & 1, sum); + xer.ca = !c0 | c1; + gpr[utils::RD(instr)] = sum; +} + +void broadway::subfic(ircolib::u32 instr) { + ircolib::u32 sum; + bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], 1, &sum); + bool c1 = __builtin_add_overflow(sum, utils::SIMM(instr), &sum); + xer.ca = !c0 | c1; + gpr[utils::RD(instr)] = sum; +} + +void broadway::subfe(ircolib::u32 instr) { + ircolib::u32 sum; + bool c0 = __builtin_add_overflow(~gpr[utils::RA(instr)], gpr[utils::RB(instr)], &sum); + bool c1 = __builtin_add_overflow(sum, xer.ca, &sum); + cr0_update(instr & 1, sum); + xer.ca = c0 | c1; + gpr[utils::RD(instr)] = sum; +} + void broadway:: or (ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] | gpr[utils::RB(instr)]; cr0_update(instr & 1, gpr[utils::RA(instr)]); } +void broadway::xori(ircolib::u32 instr) { gpr[utils::RA(instr)] = gpr[utils::RS(instr)] ^ utils::UIMM(instr); } + void broadway::mullw(ircolib::u32 instr) { gpr[utils::RD(instr)] = ircolib::u64(gpr[utils::RA(instr)]) * ircolib::u64(gpr[utils::RB(instr)]); } @@ -543,4 +634,27 @@ void broadway::divwu(ircolib::u32 instr) { gpr[utils::RD(instr)] = dividend / divisor; cr0_update(instr & 1, gpr[utils::RD(instr)]); } + +void broadway::mftb(ircolib::u32 instr) { + const ircolib::u32 tbr = (instr >> 11) & 0x3FF; + + if (tbr != 392 && tbr != 424) + ircolib::panic("broadway::mftb with tbr != 268 && != 269 ({})", tbr); + + if (tbr == 392) + gpr[utils::RD(instr)] = tbl; + + if (tbr == 424) + gpr[utils::RD(instr)] = tbu; +} + +void broadway::sraw(ircolib::u32 instr) { + ircolib::u8 shift = std::min(gpr[utils::RB(instr)] & 0x3f, ircolib::u32(31)); + ircolib::s32 rs = gpr[utils::RS(instr)]; + ircolib::s32 result = rs >> shift; + ircolib::u32 mask = (1 << shift) - 1; + cr0_update(instr & 1, result); + xer.ca = (rs < 0) & ((ircolib::u32(rs) & mask) != 0); + gpr[utils::RA(instr)] = result; +} } // namespace weee::core diff --git a/core/broadway/mmio/ai.cpp b/core/broadway/mmio/ai.cpp index 5e6d119..98617c3 100644 --- a/core/broadway/mmio/ai.cpp +++ b/core/broadway/mmio/ai.cpp @@ -3,29 +3,29 @@ #include namespace weee::core { -ai::ai(mem &mem) { +audio_interface::audio_interface(mem &mem) { mem.register_read32_handler(0x0c006c00, 0x0c006c1f, [&](ircolib::u32 addr) { return read32(addr); }); mem.register_write32_handler(0x0c006c00, 0x0c006c1f, [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); } -ircolib::u32 ai::read32(ircolib::u32 addr) { +ircolib::u32 audio_interface::read32(ircolib::u32 addr) { switch (addr) { case 0: return ctrl.raw; default: - ircolib::panic("ai::read32 from unimplemented addr 0x{:08X}", addr); + ircolib::panic("audio_interface::read32 from unimplemented addr 0x{:08X}", addr); return 0; } } -void ai::write32(ircolib::u32 addr, ircolib::u32 value) { +void audio_interface::write32(ircolib::u32 addr, ircolib::u32 value) { switch (addr) { case 0: ctrl.raw = value; break; default: - ircolib::panic("ai::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + ircolib::panic("audio_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); } } } // namespace weee::core diff --git a/core/broadway/mmio/ai.hpp b/core/broadway/mmio/ai.hpp index d4ead02..a4cec32 100644 --- a/core/broadway/mmio/ai.hpp +++ b/core/broadway/mmio/ai.hpp @@ -3,8 +3,8 @@ namespace weee::core { struct mem; -struct ai { - ai(mem &); +struct audio_interface { + audio_interface(mem &); ircolib::u32 read32(ircolib::u32); void write32(ircolib::u32, ircolib::u32); diff --git a/core/broadway/mmio/dsp.cpp b/core/broadway/mmio/dsp.cpp index 381e673..e858362 100644 --- a/core/broadway/mmio/dsp.cpp +++ b/core/broadway/mmio/dsp.cpp @@ -7,12 +7,77 @@ dsp::dsp(mem &mem) { mem.register_read16_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr) { return read16(addr); }); mem.register_write16_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr, ircolib::u16 value) { return write16(addr, value); }); + + mem.register_read32_handler(0x0c005000, 0x0c0051ff, [&](ircolib::u32 addr) { return read32(addr); }); + mem.register_write32_handler(0x0c005000, 0x0c0051ff, + [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); +} + +ircolib::u32 dsp::read32(ircolib::u32 addr) { + switch (addr) { + case 0x20: + return ar_dma_mmaddr.whole; + case 0x24: + return ar_dma_araddr.whole; + case 0x28: + return ar_dma_cnt.whole; + case 0x30: + return dma_start_addr.whole; + default: + ircolib::panic("dsp::read32 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} + +void dsp::write32(ircolib::u32 addr, ircolib::u32 value) { + switch (addr) { + case 0x20: + ar_dma_mmaddr.whole = value; + break; + case 0x24: + ar_dma_araddr.whole = value; + break; + case 0x28: + ar_dma_cnt.whole = value; + break; + case 0x30: + dma_start_addr.whole = value; + break; + default: + ircolib::panic("dsp::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + } } ircolib::u16 dsp::read16(ircolib::u32 addr) { switch (addr) { + case 0x00: + return dsp_mail_hi; + case 0x02: + return dsp_mail_lo; + case 0x04: + return cpu_mail_hi; + case 0x06: + return cpu_mail_lo; case 0x0a: return csr.raw; + case 0x12: + return ar_size; + case 0x20: + return ar_dma_mmaddr.hi; + case 0x22: + return ar_dma_mmaddr.lo; + case 0x24: + return ar_dma_araddr.hi; + case 0x26: + return ar_dma_araddr.lo; + case 0x28: + return ar_dma_cnt.hi; + case 0x2a: + return ar_dma_cnt.lo; + case 0x30: + return dma_start_addr.hi; + case 0x32: + return dma_start_addr.lo; default: ircolib::panic("dsp::read16 from unimplemented addr 0x{:08X}", addr); return 0; @@ -21,11 +86,67 @@ ircolib::u16 dsp::read16(ircolib::u32 addr) { void dsp::write16(ircolib::u32 addr, ircolib::u16 value) { switch (addr) { + case 0x00: + dsp_mail_hi = value; + break; + case 0x02: + dsp_mail_lo = value; + break; case 0x0a: - csr.raw = value; + { + Csr ccsr = {.raw = value}; + Csr ocsr = csr; + csr = ccsr; + if (csr.res || (ocsr.boot_mode != ccsr.boot_mode && ccsr.boot_mode)) { + cpu_mail_hi = 0; + cpu_mail_lo = 0; + dsp_mail_hi = 0; + dsp_mail_lo = 0; + } + + if (csr.piint) + csr.piint = false; + + if (csr.aidint) + csr.aidint = false; + + if (csr.arint) + csr.arint = false; + + if (csr.dspint) + csr.dspint = false; + } + break; + case 0x12: + ar_size = value; + break; + case 0x20: + ar_dma_mmaddr.hi = value; + break; + case 0x22: + ar_dma_mmaddr.lo = value; + break; + case 0x24: + ar_dma_araddr.hi = value; + break; + case 0x26: + ar_dma_araddr.lo = value; + break; + case 0x28: + ar_dma_cnt.hi = value; + break; + case 0x2a: + ar_dma_cnt.lo = value; + csr.arint = true; + break; + case 0x30: + dma_start_addr.hi = value; + break; + case 0x32: + dma_start_addr.lo = value; break; default: - ircolib::panic("dsp::read16 from unimplemented addr 0x{:08X}", addr); + ircolib::panic("dsp::write16 from unimplemented addr 0x{:08X} with value 0x{:04X}", addr, value); } } } // namespace weee::core diff --git a/core/broadway/mmio/dsp.hpp b/core/broadway/mmio/dsp.hpp index d18f4a7..34f632d 100644 --- a/core/broadway/mmio/dsp.hpp +++ b/core/broadway/mmio/dsp.hpp @@ -7,8 +7,10 @@ struct dsp { dsp(mem &); ircolib::u16 read16(ircolib::u32); void write16(ircolib::u32, ircolib::u16); + ircolib::u32 read32(ircolib::u32); + void write32(ircolib::u32, ircolib::u32); - union { + union Csr { struct { unsigned res : 1; unsigned piint : 1; @@ -21,10 +23,21 @@ struct dsp { unsigned dspint_mask : 1; unsigned int_status : 1; unsigned : 1; - unsigned res2 : 1; + unsigned boot_mode : 1; unsigned : 4; }; ircolib::u16 raw; } csr; + + union { + struct { + ircolib::u32 lo; + ircolib::u32 hi; + }; + ircolib::u64 whole; + } ar_dma_mmaddr, ar_dma_araddr, ar_dma_cnt, dma_start_addr; + + ircolib::u16 ar_size; + ircolib::u16 dsp_mail_hi = 0, dsp_mail_lo = 0, cpu_mail_hi = 0, cpu_mail_lo = 0; }; } // namespace weee::core diff --git a/core/broadway/mmio/si.cpp b/core/broadway/mmio/si.cpp new file mode 100644 index 0000000..2d4c952 --- /dev/null +++ b/core/broadway/mmio/si.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +namespace weee::core { +serial_interface::serial_interface(mem &mem) { + mem.register_read32_handler(0x0c006400, 0x0c0064ff, [&](ircolib::u32 addr) { return read32(addr); }); + mem.register_write32_handler(0x0c006400, 0x0c0064ff, + [&](ircolib::u32 addr, ircolib::u32 value) { return write32(addr, value); }); +} + +ircolib::u32 serial_interface::read32(ircolib::u32 addr) { + switch (addr) { + case 0x30: + return sipoll.raw; + case 0x34: + return sicomcsr.raw; + case 0x38: + return sisr.raw; + case 0x3C: + return clock_lk.raw; + default: + ircolib::panic("serial_interface::read32 from unimplemented addr 0x{:08X}", addr); + return 0; + } +} + +void serial_interface::write32(ircolib::u32 addr, ircolib::u32 value) { + switch (addr) { + case 0x30: + sipoll.raw = value; + break; + case 0x34: + sicomcsr.raw = value; + break; + case 0x38: + sisr.raw = value; + break; + case 0x3C: + clock_lk.raw = value; + break; + default: + ircolib::panic("serial_interface::write32 to unimplemented addr 0x{:08X} with value 0x{:08X}", addr, value); + } +} +} // namespace weee::core diff --git a/core/broadway/mmio/si.hpp b/core/broadway/mmio/si.hpp new file mode 100644 index 0000000..64125c8 --- /dev/null +++ b/core/broadway/mmio/si.hpp @@ -0,0 +1,75 @@ +#pragma once +#include + +namespace weee::core { +struct mem; +struct serial_interface { + serial_interface(mem &); + + ircolib::u32 read32(ircolib::u32); + void write32(ircolib::u32, ircolib::u32); + + union { + struct { + unsigned vbcpy : 4; + unsigned en : 4; + unsigned y : 8; + unsigned x : 8; + unsigned : 8; + }; + + ircolib::u32 raw; + } sipoll; + + union { + struct { + unsigned tstart : 1; + unsigned channel : 2; + unsigned cben : 1; + unsigned cmden : 1; + unsigned inlength : 7; + unsigned : 1; + unsigned outlength : 7; + unsigned : 1; + unsigned chen : 1; + unsigned chnum : 2; + unsigned rdstintmsk : 1; + unsigned rdstint : 1; + unsigned comerr : 1; + unsigned tcintmsk : 1; + unsigned tcint : 1; + }; + ircolib::u32 raw; + } sicomcsr; + + union { + struct { + unsigned : 31; + unsigned lock : 1; + }; + + ircolib::u32 raw; + } clock_lk; + + union { + struct { + unsigned joy3 : 6; + unsigned : 2; + unsigned joy2 : 6; + unsigned : 2; + unsigned joy1 : 6; + unsigned : 2; + unsigned unrun : 1; + unsigned ovrun0 : 1; + unsigned coll0 : 1; + unsigned norep0 : 1; + unsigned wrst0 : 1; + unsigned rdst0 : 1; + unsigned : 1; + unsigned wr : 1; + }; + + ircolib::u32 raw; + } sisr; +}; +} // namespace weee::core diff --git a/core/broadway/mmio/vi.cpp b/core/broadway/mmio/vi.cpp index f8b70fc..736c49a 100644 --- a/core/broadway/mmio/vi.cpp +++ b/core/broadway/mmio/vi.cpp @@ -4,12 +4,67 @@ namespace weee::core { video_interface::video_interface(mem &mem) { + mem.register_read16_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr) { return read16(addr); }); + mem.register_read32_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr) { return read32(addr); }); mem.register_write16_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr, ircolib::u16 value) { write16(addr, value); }); mem.register_write32_handler(0x0c002000, 0x0c0020ff, [&](ircolib::u32 addr, ircolib::u32 value) { write32(addr, value); }); } +ircolib::u16 video_interface::read16(ircolib::u32 addr) { + switch (addr) { + case 0x00: + return vtr.raw; + case 0x02: + return dcr.raw; + case 0x4a: + return hsr.raw; + case 0x6c: + return viclk & 1; + case 0x70: + return 0x0280; + default: + ircolib::panic("video_interface::read16 from unimplemented addr 0x{:04X}", addr); + return 0; + } +} + +ircolib::u32 video_interface::read32(ircolib::u32 addr) { + switch (addr) { + case 0x02: + return dcr.raw; + case 0x04: + return htr0.raw; + case 0x08: + return htr1.raw; + case 0x0c: + return vto.raw; + case 0x10: + return vte.raw; + case 0x14: + return bbei.raw; + case 0x18: + return bboi.raw; + case 0x1c: + return tfbl.raw & 0x1ffffe00; + case 0x24: + return bfbl.raw & 0x10fffe00; + case 0x4c: + case 0x50: + case 0x54: + return fct0[addr - 0x4c].raw; + case 0x58: + case 0x5c: + case 0x60: + case 0x64: + return fct1[addr - 0x58].raw; + default: + ircolib::panic("video_interface::read32 from unimplemented addr 0x{:04X}", addr); + return 0; + } +} + void video_interface::write16(ircolib::u32 addr, ircolib::u16 value) { switch (addr) { case 0x00: diff --git a/core/broadway/mmio/vi.hpp b/core/broadway/mmio/vi.hpp index 080b0eb..77388b3 100644 --- a/core/broadway/mmio/vi.hpp +++ b/core/broadway/mmio/vi.hpp @@ -8,6 +8,9 @@ struct video_interface { video_interface(mem &); void write16(ircolib::u32, ircolib::u16); void write32(ircolib::u32, ircolib::u32); + ircolib::u16 read16(ircolib::u32); + ircolib::u32 read32(ircolib::u32); + ircolib::u32 xfb_top_addr() { auto addr = tfbl.fbb; if (tfbl.page) { @@ -96,7 +99,7 @@ struct video_interface { unsigned fbb : 24; }; ircolib::u32 raw; - } tfbl, bfbl; + } tfbl{}, bfbl{}; union FCT012 { struct { diff --git a/core/mem.cpp b/core/mem.cpp index f0c8afa..bb608f3 100644 --- a/core/mem.cpp +++ b/core/mem.cpp @@ -4,7 +4,7 @@ #include namespace weee::core { -mem::mem() : vi(*this), pi(*this), mi(*this), dsp(*this), ai(*this), exi(*this) { +mem::mem() : vi(*this), pi(*this), mi(*this), dsp(*this), ai(*this), exi(*this), si(*this) { mem1.resize(24_mib); std::fill(mem1.begin(), mem1.end(), 0); ipl.resize(1_mib); diff --git a/core/mem.hpp b/core/mem.hpp index 0b7a742..35a2449 100644 --- a/core/mem.hpp +++ b/core/mem.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -92,6 +93,7 @@ struct mem { memory_interface mi; dsp dsp; exi exi; - ai ai; + audio_interface ai; + serial_interface si; }; } // namespace weee::core diff --git a/main.cpp b/main.cpp index d6a1afb..84ad9ad 100644 --- a/main.cpp +++ b/main.cpp @@ -67,7 +67,7 @@ int main(int argc, char **argv) { open = false; } - SDL_ConvertPixels(640, 240, SDL_PIXELFORMAT_UYVY, &mem.mem1[vi.xfb_top_addr()], 640 * 4, SDL_PIXELFORMAT_BGR24, + SDL_ConvertPixels(640, 240, SDL_PIXELFORMAT_UYVY, &mem.mem1[0], 640 * 4, SDL_PIXELFORMAT_BGR24, rgbTexture.data(), 640 * 3); SDL_RenderClear(renderer);