Annotation of nono/vm/ssg.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2024 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // SSG (YM2149)
                      9: //
                     10: 
                     11: #include "ssg.h"
1.1.1.2 ! root       12: #include "monitor.h"
1.1       root       13: 
                     14: // コンストラクタ
                     15: SSGDevice::SSGDevice()
                     16:        : inherited(OBJ_SSG)
                     17: {
1.1.1.2 ! root       18:        monitor = gMonitorManager->Regist(ID_MONITOR_SSG, this);
        !            19:        monitor->func = ToMonitorCallback(&SSGDevice::MonitorUpdate);
        !            20:        monitor->SetSize(45, 12);
1.1       root       21: }
                     22: 
                     23: // デストラクタ
                     24: SSGDevice::~SSGDevice()
                     25: {
                     26: }
                     27: 
                     28: // リセット
                     29: void
                     30: SSGDevice::ResetHard(bool poweron)
                     31: {
                     32: }
                     33: 
                     34: // A0 でアドレスポートとデータポートを分けるみたいなのではなく、
                     35: // 謎の BDIR と BC1 を R/W と A0 につないであるっぽい感じなので、
                     36: // トラップみたいな配置になっている。(紙資料も間違えている…)
                     37: //
                     38: // BDIR BC1        ->  XP I/O
                     39: //  0    0  Inactive
                     40: //  0    1  Read               0x83 R
                     41: //  1    0  Write              0x82 W
                     42: //  1    1  Address            0x83 W
                     43: 
                     44: busdata
                     45: SSGDevice::Read1(uint32 addr)
                     46: {
                     47:        uint32 offset = addr & 1;
                     48:        uint32 data;
                     49: 
                     50:        if (offset == 0) {
                     51:                data = 0xff;    // ?
                     52:        } else {
                     53:                // 読み込み
                     54:                data = reg.Get(regno);
                     55:                putlog(3, "R%x -> $%02x", regno, data);
                     56:        }
                     57: 
                     58:        return data;
                     59: }
                     60: 
                     61: busdata
                     62: SSGDevice::Write1(uint32 addr, uint32 data)
                     63: {
                     64:        uint32 offset = addr & 1;
                     65: 
                     66:        if (offset == 0) {
                     67:                // データ書き込み
                     68:                putlog(2, "R%x <- $%02x", regno, data);
                     69:                switch (regno) {
                     70:                 case 0x0:      // Frequency of channel A (Low)
                     71:                        reg.freq[0] &= 0xf00;
                     72:                        reg.freq[0] |= data;
                     73:                        break;
                     74:                 case 0x1:      // Frequency of channel A (High)
                     75:                        reg.freq[0] &= 0x0ff;
                     76:                        reg.freq[0] |= data << 8;
                     77:                        break;
                     78:                 case 0x2:      // Frequency of channel B (Low)
                     79:                        reg.freq[1] &= 0xf00;
                     80:                        reg.freq[1] |= data;
                     81:                        break;
                     82:                 case 0x3:      // Frequency of channel B (High)
                     83:                        reg.freq[1] &= 0x0ff;
                     84:                        reg.freq[1] |= data << 8;
                     85:                        break;
                     86:                 case 0x4:      // Frequency of channel C (Low)
                     87:                        reg.freq[2] &= 0xf00;
                     88:                        reg.freq[2] |= data;
                     89:                        break;
                     90:                 case 0x5:      // Frequency of channel C (High)
                     91:                        reg.freq[2] &= 0x0ff;
                     92:                        reg.freq[2] |= data << 8;
                     93:                        break;
                     94: 
                     95:                 case 0x6:      // Frequency of noise
                     96:                        reg.noise_freq = data & 0x1f;
                     97:                        break;
                     98: 
                     99:                 case 0x7:      // I/O port and mixer settings
                    100:                        reg.settings = data;
                    101:                        break;
                    102: 
                    103:                 case 0x8:      // Level of channel A
                    104:                        reg.ampmode[0] = (data & 0x10);
                    105:                        reg.amplevel[0] = data & 0x0f;
                    106:                        break;
                    107:                 case 0x9:      // Level of channel B
                    108:                        reg.ampmode[1] = (data & 0x10);
                    109:                        reg.amplevel[1] = data & 0x0f;
                    110:                        break;
                    111:                 case 0xa:      // Level of channel C
                    112:                        reg.ampmode[2] = (data & 0x10);
                    113:                        reg.amplevel[2] = data & 0x0f;
                    114:                        break;
                    115: 
                    116:                 case 0xb:      // Frequency of envelope (Low)
                    117:                        reg.envelope_freq &= 0xff00;
                    118:                        reg.envelope_freq |= data;
                    119:                        break;
                    120:                 case 0xc:      // Frequency of envelope (Hight)
                    121:                        reg.envelope_freq &= 0x00ff;
                    122:                        reg.envelope_freq |= data << 8;
                    123:                        break;
                    124: 
                    125:                 case 0xd:      // Shape of envelope
                    126:                        reg.envelope_shape = data & 0x0f;
                    127:                        break;
                    128: 
                    129:                 case 0xe:      // Data of I/O port A
                    130:                        reg.dataA = data;
                    131:                        break;
                    132:                 case 0xf:      // Data of I/O port B
                    133:                        reg.dataB = data;
                    134:                        break;
                    135: 
                    136:                 default:
                    137:                        assertmsg(false, "regno=$%x", regno);
                    138:                        break;
                    139:                }
                    140:        } else {
                    141:                // アドレス書き込み
                    142:                regno = data & 0x0f;
                    143:                putlog(4, "reg <- $%x", regno);
                    144:        }
                    145: 
                    146:        return 0;
                    147: }
                    148: 
                    149: busdata
                    150: SSGDevice::Peek1(uint32 addr)
                    151: {
                    152:        return reg.Get(regno);
                    153: }
                    154: 
                    155: void
                    156: SSGDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    157: {
                    158:        // 012345678901234567890
                    159:        // R1/R0 Freq ChA  $xxx f=
                    160:        // R3/R2 Freq ChB  $xxx
                    161:        // R5/R4 Freq ChC  $xxx
                    162:        // R6    FreqNoise  $xx
                    163:        // R7    Settings   $xx(IB IA NC NB NA TC TB TA)
                    164:        // R8    Level A    $xx
                    165:        // R9    Level B    $xx
                    166:        // Ra    Level C    $xx
                    167:        // Rc/Rb EnvFreq  $xxxx
                    168:        // Rd    EnvShape   $xx
                    169:        // Re    Data A     $xx
                    170:        // Rf    Data A     $xx
                    171: 
                    172:        uint f;
                    173:        int y = 0;
                    174: 
                    175:        screen.Clear();
                    176: 
                    177:        SSG tmp = reg;
                    178: 
                    179:        for (int i = 0; i < 3; i++) {
                    180:                if (__predict_false(tmp.freq[i] == 0)) {
                    181:                        f = 0;
                    182:                } else {
                    183:                        f = fMaster / (16 * tmp.freq[i]);
                    184:                }
                    185:                screen.Print(0, y, "R%u/R%u Freq Ch%c  $%03x f=%u",
                    186:                        i * 2 + 1, i * 2, 'A' + i, tmp.freq[i], f);
                    187:                y++;
                    188:        }
                    189: 
                    190:        if (__predict_false(tmp.noise_freq == 0)) {
                    191:                f = 0;
                    192:        } else {
                    193:                f = fMaster / (16 * tmp.noise_freq);
                    194:        }
                    195:        screen.Print(0, y++, "R6    FreqNoise  $%02x f=%u", tmp.noise_freq, f);
                    196: 
                    197:        screen.Print(0, y, "R7    Settings   $%02x(", tmp.settings);
                    198:        screen.Puts(21, y, TA::OnOff(tmp.settings & 0x80), "IB");
                    199:        screen.Puts(24, y, TA::OnOff(tmp.settings & 0x40), "IA");
                    200:        screen.Puts(27, y, TA::OnOff(tmp.settings & 0x20), "NC");
                    201:        screen.Puts(30, y, TA::OnOff(tmp.settings & 0x10), "NB");
                    202:        screen.Puts(33, y, TA::OnOff(tmp.settings & 0x08), "NA");
                    203:        screen.Puts(36, y, TA::OnOff(tmp.settings & 0x04), "TA");
                    204:        screen.Puts(39, y, TA::OnOff(tmp.settings & 0x02), "TA");
                    205:        screen.Puts(42, y, TA::OnOff(tmp.settings & 0x01), "TA");
                    206:        screen.Putc(44, y, ')');
                    207:        y++;
                    208: 
                    209:        for (int i = 0; i < 3; i++) {
                    210:                screen.Print(0, y++, "R%x    Level %c    $%02x",
                    211:                        8 + i, 'A' + i, tmp.GetLevelReg(i));
                    212:        }
                    213: 
                    214:        if (__predict_false(tmp.envelope_freq == 0)) {
                    215:                f = 0;
                    216:        } else {
                    217:                f = fMaster / (256 * tmp.envelope_freq);
                    218:        }
                    219:        screen.Print(0, y++, "Rc/Rb EnvFreq  $%04x f=%u", tmp.envelope_freq, f);
                    220: 
                    221:        // モニタはソースコードのマルチバイト文字(UTF-8) を SJIS に変換する所は
                    222:        // (まだ?)用意してないので、こっちで SJIS 文字列を用意する必要がある。
                    223:        #define H       "\x81\x50"
                    224:        #define L       "\x81\x51"
                    225:        #define U       "\x81\x5e"
                    226:        #define D       "\x81\x5f"
                    227:        static const char *shape8[8] = {
                    228:                D D D D D,      // "\\\\\"
                    229:                D L L L L,      // "\____"
                    230:                D U D U D,      // "\/\/\"
                    231:                D H H H H,      // "\ ̄ ̄ ̄ ̄"
                    232:                U U U U U,      // "/////"
                    233:                U H H H H,      // "/ ̄ ̄ ̄ ̄"
                    234:                U D U D U,      // "/\/\/"
                    235:                U L L L L,      // "/____"
                    236:        };
                    237:        const char *shape;
                    238:        uint es = tmp.envelope_shape;
                    239:        if (es >= 8) {
                    240:                shape = shape8[es - 8];
                    241:        } else if (es >= 4) {
                    242:                shape = shape8[7];
                    243:        } else {
                    244:                shape = shape8[1];
                    245:        }
                    246:        screen.Print(0, y++, "Rd    EnvShape   $%02x %s",
                    247:                tmp.envelope_shape, shape);
                    248:        screen.Print(0, y++, "Re    Data A     $%02x", tmp.dataA);
                    249:        screen.Print(0, y++, "Rf    Data B     $%02x", tmp.dataB);
                    250: }
                    251: 
                    252: // レジスタの内容を副作用なく返す。
                    253: uint32
                    254: SSG::Get(uint n) const
                    255: {
                    256:        switch (n) {
                    257:         case 0x0:
                    258:                return freq[0] & 0xff;
                    259:         case 0x1:
                    260:                return freq[0] >> 8;
                    261:         case 0x2:
                    262:                return freq[1] & 0xff;
                    263:         case 0x3:
                    264:                return freq[1] >> 8;
                    265:         case 0x4:
                    266:                return freq[2] & 0xff;
                    267:         case 0x5:
                    268:                return freq[2] >> 8;
                    269:         case 0x6:
                    270:                return noise_freq;
                    271:         case 0x7:
                    272:                return settings;
                    273:         case 0x8:
                    274:                return GetLevelReg(0);
                    275:         case 0x9:
                    276:                return GetLevelReg(1);
                    277:         case 0xa:
                    278:                return GetLevelReg(2);
                    279:         case 0xb:
                    280:                return envelope_freq & 0xff;
                    281:         case 0xc:
                    282:                return envelope_freq >> 8;
                    283:         case 0xd:
                    284:                return envelope_shape;
                    285:         case 0xe:
                    286:                return dataA;
                    287:         case 0xf:
                    288:                return dataB;
                    289:         default:
                    290:                __unreachable();
                    291:        }
                    292: }

unix.superglobalmegacorp.com

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