|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.4 root 7: //
8: // OPM (YM2151)
9: //
10:
1.1 root 11: #include "opm.h"
1.1.1.5 root 12: #include "adpcm.h"
1.1.1.10 root 13: #include "event.h"
1.1.1.4 root 14: #include "fdc.h"
1.1.1.11! root 15: #include "mainbus.h"
1.1.1.5 root 16: #include "mpu.h"
17: #include "scheduler.h"
1.1 root 18:
1.1.1.4 root 19: // コンストラクタ
1.1 root 20: OPMDevice::OPMDevice()
1.1.1.6 root 21: : inherited(OBJ_OPM)
1.1 root 22: {
23: }
24:
1.1.1.4 root 25: // デストラクタ
1.1 root 26: OPMDevice::~OPMDevice()
27: {
1.1.1.6 root 28: }
29:
30: // 初期化
31: bool
32: OPMDevice::Init()
33: {
34: adpcm = GetADPCMDevice();
35: fdc = GetFDCDevice();
36:
37: return true;
1.1 root 38: }
39:
1.1.1.5 root 40: // リセット
41: void
42: OPMDevice::ResetHard(bool poweron)
43: {
44: busy_origin = 0;
45: busy_start = 0;
46: busy_end = 0;
47:
1.1.1.6 root 48: fdc->SetForceReady(false);
1.1.1.5 root 49: }
50:
1.1.1.7 root 51: busdata
1.1.1.8 root 52: OPMDevice::ReadPort(uint32 offset)
1.1 root 53: {
1.1.1.7 root 54: busdata data;
1.1.1.5 root 55:
1.1.1.4 root 56: switch (offset) {
57: case 0:
1.1.1.11! root 58: putlog(0, "Read $%06x (NOT IMPLEMENTED)",
! 59: GetMainbusDevice()->GetPaddr());
1.1.1.7 root 60: data = 0;
61: break;
1.1.1.4 root 62: case 1:
63: // OPM ステータスレジスタ
1.1.1.5 root 64: data = 0;
65: if (IsBusy()) {
66: data |= 0x80;
67: }
68: // タイマ関係の bit1, bit0 は未実装
69:
1.1.1.7 root 70: putlog(1, "STAT -> $%02x", data.Data());
71: break;
1.1.1.4 root 72: default:
1.1.1.8 root 73: VMPANIC("corrupted offset=%u", offset);
1.1.1.7 root 74: data = 0xff;
75: break;
1.1.1.4 root 76: }
1.1.1.7 root 77:
78: // InsideOut p.135
1.1.1.8 root 79: const busdata read_wait = busdata::Wait(19 * 40_nsec);
1.1.1.7 root 80: data |= read_wait;
81:
1.1.1.8 root 82: data |= BusData::Size1;
1.1.1.7 root 83: return data;
1.1 root 84: }
85:
1.1.1.7 root 86: busdata
1.1.1.8 root 87: OPMDevice::WritePort(uint32 offset, uint32 data)
1.1 root 88: {
1.1.1.6 root 89: uint64 now = scheduler->GetVirtTime();
1.1.1.5 root 90:
1.1.1.4 root 91: switch (offset) {
92: case 0:
93: putlog(1, "REG <- $%02x", data);
1.1.1.5 root 94: // アドレス選択が反映されるまで 8 クロックかかるらしい
95: // が、顕在化しないと思うので実装していない
1.1.1.4 root 96: reg = data;
97: break;
98: case 1:
99: putlog(1, "DATA <- $%02x", data);
1.1.1.5 root 100: // CPU が命令中のどのタイミングでライトするかを用意していないので
101: // 実際に OPM にライトされるタイミングは正確にはわからない。
102: // なので正確な時刻の起点は不明。
103: //
104: // BUSY がアサートされるまで OPM クロックで 8 から 12 クロックかかる
105: // らしい。
106: //
107: // BUSY のアサート期間は 68 クロックらしい。
108: // YM2151 アプリケーションマニュアル(英語版) 2.1.1
109:
110: // BUSY フラグのみならず、書き込み処理期間中のときは保証されていない。
111: // とりあえず無視する。
112: if (busy_origin <= now && now < busy_end) {
113: putlog(0, "Write on Busy");
114: break;
115: }
116:
117: // 時刻の起点は CPU 側の命令によって異なるはずだが
118: // わからないので命令のぶんは無視しておく。
119: // 53 クロックのウェイトのほうは足す。
1.1.1.11! root 120: busy_origin = now + 53 * mpu->GetClock_tsec();
1.1.1.5 root 121:
122: // busy_start のほうはとりあえず 10 クロックにしておく。
123: busy_start = busy_origin + 10 * clk;
124: busy_end = busy_origin + 68 * clk;
125:
1.1.1.4 root 126: switch (reg) {
127: case 0x1b:
1.1.1.6 root 128: adpcm->SetClock(data & 0x80);
129: fdc->SetForceReady(data & 0x40);
1.1.1.4 root 130: // 他のビットは未対応
131: break;
132: default:
1.1.1.5 root 133: putlog(0, "Write $%06x <- $%02x (NOT IMPLEMENTED)",
1.1.1.11! root 134: GetMainbusDevice()->GetPaddr(), data);
1.1.1.4 root 135: break;
136: }
137: break;
138: default:
1.1.1.8 root 139: VMPANIC("corrupted offset=%u", offset);
1.1.1.6 root 140: break;
1.1.1.4 root 141: }
142:
1.1.1.7 root 143: // InsideOut p.135
144: const busdata write_wait = busdata::Wait(53 * 40_nsec);
145:
1.1.1.8 root 146: busdata r = write_wait;
147: r |= BusData::Size1;
148: return r;
1.1 root 149: }
150:
1.1.1.7 root 151: busdata
1.1.1.8 root 152: OPMDevice::PeekPort(uint32 offset)
1.1 root 153: {
154: // XXX 未実装
155: return 0xff;
156: }
1.1.1.5 root 157:
1.1.1.8 root 158: bool
159: OPMDevice::PokePort(uint32 offset, uint32 data)
160: {
161: return false;
162: }
163:
1.1.1.5 root 164: // OPM ステータスレジスタの B (BUSY) ビット
165: bool
166: OPMDevice::IsBusy() const
167: {
1.1.1.6 root 168: uint64 now = scheduler->GetVirtTime();
1.1.1.5 root 169:
170: return (busy_start <= now && now < busy_end);
171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.