From 872d2c2766536a372af5d1048bed7514078f9d31 Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 3 Oct 2022 00:31:53 +0300 Subject: Impl vblank irq --- emulator.cpp | 20 +++++++++++--------- vdp.cpp | 31 +++++++++++++++++++++++++++++++ vdp.hpp | 4 ++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/emulator.cpp b/emulator.cpp index b5ad031..de9be02 100644 --- a/emulator.cpp +++ b/emulator.cpp @@ -328,8 +328,8 @@ int m68k_irq_ack(int level) { (void) level; // TODO - exit_error("IRQ ack"); - return M68K_INT_ACK_SPURIOUS; + printf("IRQ ack\n"); + return level; } static void make_hex(char* buff, unsigned int pc, unsigned int length) @@ -480,17 +480,19 @@ int emulator(M68KDebuggingControl& m68k_debug) break; } if (m68k_debug.IsRunning()) { - m68k_execute(10000); + do { + m68k_execute(100000); + } while(!g_vdp.Scanline()); } if (m68k_debug.HasBreakpoint()) { m68k_debug.SetRunning(false); m68k_debug.ResetPendingBreakpoint(); - const auto response = - exchange_ctx.WrapDataToSend("S05"); - if (DEBUG_TRACE_GDB_REMOTE) - printf("-> \"%s\"\n", response.c_str()); - if (send(conn_fd, &response[0], response.length(), 0) == -1) - perror("Send failed (response)"); + const auto response = + exchange_ctx.WrapDataToSend("S05"); + if (DEBUG_TRACE_GDB_REMOTE) + printf("-> \"%s\"\n", response.c_str()); + if (send(conn_fd, &response[0], response.length(), 0) == -1) + perror("Send failed (response)"); } // TODO turn off O_NONBLOCK and poll instead of sleep, only use // nonlock when freerunning diff --git a/vdp.cpp b/vdp.cpp index 74b9f65..e497bdf 100644 --- a/vdp.cpp +++ b/vdp.cpp @@ -2,6 +2,7 @@ */ #include "vdp.hpp" +#include "musashi-m68k/m68k.h" #include #include @@ -75,6 +76,36 @@ void VDP::Write(const uint32_t offset, const enum bitness bitness, const uint32_ } } +#define MODESET2_DISP_MASK (1) +#define MODESET2_DISP_SHIFT (6) +#define MODESET2_DISP_EXTRACT(reg) \ + (((reg) & (MODESET2_DISP_MASK << MODESET2_DISP_SHIFT)) >> MODESET2_DISP_SHIFT) + +#define MODESET2_IE0_MASK (1) +#define MODESET2_IE0_SHIFT (5) +#define MODESET2_IE0_EXTRACT(reg) \ + (((reg) & (MODESET2_IE0_MASK << MODESET2_IE0_SHIFT)) >> MODESET2_IE0_SHIFT) + +bool VDP::Scanline() +{ + const uint16_t mode_set_2 = _reg[static_cast(RegID::kModeSet2)]; + if (!MODESET2_DISP_EXTRACT(mode_set_2)) { + return true; + } + _lines_counter++; + const uint16_t lines_per_screen = _status.pal_mode ? kLinesPerScreenPAL : kLinesPerScreenNTSC; + if (_lines_counter >= lines_per_screen) { + _lines_counter = 0; + if (MODESET2_IE0_EXTRACT(mode_set_2)) { + m68k_set_irq(6); + _status.vblank = true; + return true; + } + } + _status.vblank = false; + return false; +} + void VDP::Reset() { _status = {}; diff --git a/vdp.hpp b/vdp.hpp index cd93938..9357377 100644 --- a/vdp.hpp +++ b/vdp.hpp @@ -13,6 +13,7 @@ class VDP { 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(); const uint32_t base_address; @@ -76,9 +77,12 @@ class VDP { 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{}; + uint16_t _lines_counter{}; uint8_t _address_mode{}; uint16_t _address{}; uint8_t _reg[kRegistersCount]{}; -- cgit v1.2.3