2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
14 //#define _DEBUG_PC80S31K
16 #define SET_BANK(s, e, w, r) { \
17 int sb = (s) >> 13, eb = (e) >> 13; \
18 for(int i = sb; i <= eb; i++) { \
22 wbank[i] = (w) + 0x2000 * (i - sb); \
27 rbank[i] = (r) + 0x2000 * (i - sb); \
32 void PC80S31K::initialize()
35 memset(rom, 0xff, sizeof(rom));
36 memset(ram, 0, sizeof(ram));
37 memset(rdmy, 0xff, sizeof(rdmy));
40 FILEIO* fio = new FILEIO();
41 if(fio->Fopen(create_local_path(_T("PC88.ROM")), FILEIO_READ_BINARY)) {
42 fio->Fseek(0x14000, FILEIO_SEEK_CUR);
43 fio->Fread(rom, sizeof(rom), 1);
45 } else if(fio->Fopen(create_local_path(_T("DISK.ROM")), FILEIO_READ_BINARY)) {
46 fio->Fread(rom, sizeof(rom), 1);
50 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
55 SET_BANK(0x0000, 0x1fff, wdmy, rom);
56 SET_BANK(0x2000, 0x3fff, wdmy, rdmy);
57 SET_BANK(0x4000, 0x7fff, ram, ram);
58 SET_BANK(0x8000, 0xffff, wdmy, rdmy);
61 // both drives always set force ready signal
62 d_fdc->write_signal(SIG_UPD765A_FREADY, 1, 1);
65 void PC80S31K::reset()
67 d_fdc->set_drive_type(0, DRIVE_TYPE_2D);
68 d_fdc->set_drive_type(1, DRIVE_TYPE_2D);
71 d_pio->write_io8(1, 0);
72 d_pio->write_io8(2, 0);
75 uint32_t PC80S31K::read_data8(uint32_t addr)
78 return rbank[addr >> 13][addr & 0x1fff];
81 uint32_t PC80S31K::fetch_op(uint32_t addr, int *wait)
84 #ifdef PC80S31K_NO_WAIT
86 // no access wait (both ROM and RAM)
89 *wait = (addr < 0x2000) ? 1 : 0;
91 return rbank[addr >> 13][addr & 0x1fff];
94 void PC80S31K::write_data8(uint32_t addr, uint32_t data)
97 if(addr == 0x7f15 && data == 0x1f && d_cpu->get_pc() < 0x2000) {
98 // ugly patch to enable both #1 and #2 drives
101 wbank[addr >> 13][addr & 0x1fff] = data;
104 uint32_t PC80S31K::read_io8(uint32_t addr)
108 switch(addr & 0xff) {
110 d_fdc->write_signal(SIG_UPD765A_TC, 1, 1);
114 return d_fdc->read_io8(addr & 1);
117 val = d_pio->read_io8(addr & 3);
118 #ifdef _DEBUG_PC80S31K
119 this->out_debug_log(_T("SUB\tIN RECV(%d)=%2x\n"), addr & 3, val);
123 val = d_pio->read_io8(addr & 3);
124 #ifdef _DEBUG_PC80S31K
126 static uint32_t prev = -1;
128 // this->out_debug_log(_T("SUB\tIN DAV=%d,RFD=%d,DAC=%d,ATN=%d\n"), val&1, (val>>1)&1, (val>>2)&1, (val>>3)&1);
138 void PC80S31K::write_io8(uint32_t addr, uint32_t data)
140 switch(addr & 0xff) {
143 // MR/MH/MA/MA2/MA... type ROM only
144 if(rom[0x7ee] != 0xfe) {
147 for(int drv = 0; drv < 2; drv++) {
148 uint32_t mode = data >> drv;
150 d_fdc->set_drive_type(drv, DRIVE_TYPE_2HD);
151 } else if(mode & 4) {
152 d_fdc->set_drive_type(drv, DRIVE_TYPE_2DD);
154 d_fdc->set_drive_type(drv, DRIVE_TYPE_2D);
159 // external printer port
162 // TODO: we need to update uPD765A to let the motor of each drive on/off
165 d_fdc->write_io8(addr & 1, data);
169 #ifdef _DEBUG_PC80S31K
170 this->out_debug_log(_T("SUB\tOUT SEND(%d)=%2x\n"), addr & 3, data);
172 d_pio->write_io8(addr & 3, data);
175 // this->out_debug_log(_T("SUB\tOUT DAV=%d,RFD=%d,DAC=%d,ATN=%d\n"), (data>>4)&1, (data>>5)&1, (data>>6)&1, (data>>7)&1);
176 d_pio->write_io8(addr & 3, data);
180 int bit = (data >> 1) & 7;
182 // this->out_debug_log(_T("SUB\tOUT DAV=%d\n"), data & 1);
183 } else if(bit == 5) {
184 // this->out_debug_log(_T("SUB\tOUT RFD=%d\n"), data & 1);
185 } else if(bit == 6) {
186 // this->out_debug_log(_T("SUB\tOUT DAC=%d\n"), data & 1);
187 } else if(bit == 7) {
188 // this->out_debug_log(_T("SUB\tOUT ATN=%d\n"), data & 1);
191 d_pio->write_io8(addr & 3, data);
196 uint32_t PC80S31K::get_intr_ack()
201 #define STATE_VERSION 1
203 void PC80S31K::save_state(FILEIO* state_fio)
205 state_fio->FputUint32(STATE_VERSION);
206 state_fio->FputInt32(this_device_id);
208 state_fio->Fwrite(ram, sizeof(ram), 1);
211 bool PC80S31K::load_state(FILEIO* state_fio)
213 if(state_fio->FgetUint32() != STATE_VERSION) {
216 if(state_fio->FgetInt32() != this_device_id) {
219 state_fio->Fread(ram, sizeof(ram), 1);