Annotation of nono/vm/opm.cpp, revision 1.1.1.11

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.