summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--emulator.cpp20
-rw-r--r--vdp.cpp31
-rw-r--r--vdp.hpp4
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 <cstring>
#include <cstdio>
@@ -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<size_t>(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]{};