--- nono/vm/dmac.cpp 2026/04/29 17:04:35 1.1.1.3 +++ nono/vm/dmac.cpp 2026/04/29 17:04:41 1.1.1.5 @@ -18,7 +18,7 @@ DMACDevice::DMACDevice() devaddr = baseaddr; devlen = 0x2000; - monitor.Init(80, 30); + monitor_size = nnSize(80, 30); for (int i = 0; i < countof(dmac.chan); i++) { dmac.chan[i].ch = i; @@ -41,12 +41,47 @@ DMACDevice::~DMACDevice() { } +void +DMACDevice::ResetHard() +{ + putlog(2, "リセット"); + + // Clears GCR, DCR, OCR, SCR, CCR, CSR, CPR and CER for all channels. + // NIV and EIV are all set to $0F (uninitialized interrupt vector). + // MTC, MAR, DAR, BTC, BAR, MFC, DFC and BFC are not affected. + + dmac.gcr = 0; + for (int ch = 0; ch < countof(dmac.chan); ch++) { + DMAC::Channel *chan = &dmac.chan[ch]; + chan->dcr = 0; + chan->ocr = 0; + chan->scr = 0; + chan->ccr = 0; + chan->int_enable = false; + chan->csr = 0; + chan->active = false; + chan->pcl = false; + chan->cpr = 0; + chan->cer = 0; + + chan->niv = 0x0f; + chan->eiv = 0x0f; + } + + // イベントをすべて停止 + for (int i = 0; i < countof(event); i++) { + event[i].Stop(); + } +} + uint64 DMACDevice::Read(uint32 addr) { uint8 data; int ch; + gMPU->AddCycle(37); // InsideOut p.135 + ch = addr / 0x40; DMAC::Channel *chan = &dmac.chan[ch]; int n = addr % 0x40; @@ -203,6 +238,8 @@ DMACDevice::Write(uint32 addr, uint32 da { int ch; + gMPU->AddCycle(31); // InsideOut p.135 + ch = addr / 0x40; DMAC::Channel *chan = &dmac.chan[ch]; int n = addr % 0x40; @@ -475,8 +512,8 @@ DMACDevice::Peek(uint32 addr) return data; } -bool -DMACDevice::MonitorUpdate() +void +DMACDevice::MonitorUpdate(TextScreen& monitor) { int x; int y; @@ -527,8 +564,8 @@ DMACDevice::MonitorUpdate() static const char * const csrname[] = { "COC", "BTC", "NDT", "ERR", "ACT", "---", "PCT", "PCS", }; - MonitorReg4(x, y++, val >> 4, &csrname[0]); - MonitorReg4(x, y++, val & 0xff, &csrname[4]); + MonitorReg4(monitor, x, y++, val >> 4, &csrname[0]); + MonitorReg4(monitor, x, y++, val & 0xff, &csrname[4]); // CER val = chan->cer & 0x1f; @@ -639,8 +676,8 @@ DMACDevice::MonitorUpdate() static const char * const ccrnames[] = { "STR", "CNT", "HLT", "SAB", "INT", "---", "---", "---", }; - MonitorReg4(x, y++, (val >> 4), &ccrnames[0]); - MonitorReg4(x, y++, (val & 0xff), &ccrnames[4]); + MonitorReg4(monitor, x, y++, (val >> 4), &ccrnames[0]); + MonitorReg4(monitor, x, y++, (val & 0xff), &ccrnames[4]); // MTC monitor.Print(x, y++, "$%04x", chan->mtc); @@ -684,13 +721,12 @@ DMACDevice::MonitorUpdate() monitor.Print(x - 5, y++, "GCR: $%02x", dmac.gcr); } } - - return true; } // 4ビット分を表示する。MonitorUpdate の下請け void -DMACDevice::MonitorReg4(int x, int y, uint32 reg, const char * const *names) +DMACDevice::MonitorReg4(TextScreen& monitor, + int x, int y, uint32 reg, const char * const *names) { for (int i = 0; i < 4; i++) { bool b = reg & (1 << (3 - i)); @@ -822,7 +858,7 @@ DMAC::Channel::SetINT(uint32 val) } } -// 転送開始 +// 転送開始 (チャンネル側) void DMAC::Channel::StartTransfer() { @@ -860,7 +896,7 @@ DMAC::Channel::StartTransfer() case DMAC::OCR_REQG_AUTO_MAX: // 自発的に転送を開始する - parent->Transfer(ch); + parent->StartTransfer(this); break; case DMAC::OCR_REQG_EXTERNAL: @@ -873,11 +909,21 @@ DMAC::Channel::StartTransfer() } } +// 転送開始 (デバイス側) +// (チャンネルが転送開始する際にデバイス側の private 変数(event[])が必要に +// なるため、プロキシしている) +void +DMACDevice::StartTransfer(DMAC::Channel *chan) +{ + Transfer(event[chan->ch]); +} + // 転送 // (イベントを持つのでこれはデバイスクラスのメソッド) void -DMACDevice::Transfer(int ch) +DMACDevice::Transfer(Event& ev) { + int& ch = ev.code; DMAC::Channel *chan = &dmac.chan[ch]; int64 rv; @@ -939,8 +985,8 @@ DMACDevice::Transfer(int ch) } else { // 次回の転送 // XXX とりあえず 1us で1回の転送にする - event[ch].time = 1_usec; - event[ch].Start(); + ev.time = 1_usec; + ev.Start(); } }