OSDN Git Service

[VM][COMMON_VM] Include IO:: class to common_vm.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc80s31k.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2011.12.18-
6
7         [ PC-80S31K ]
8 */
9
10 #include "pc80s31k.h"
11 #include "disk.h"
12 #include "upd765a.h"
13
14 //#define _DEBUG_PC80S31K
15
16 #define SET_BANK(s, e, w, r) { \
17         int sb = (s) >> 13, eb = (e) >> 13; \
18         for(int i = sb; i <= eb; i++) { \
19                 if((w) == wdmy) { \
20                         wbank[i] = wdmy; \
21                 } else { \
22                         wbank[i] = (w) + 0x2000 * (i - sb); \
23                 } \
24                 if((r) == rdmy) { \
25                         rbank[i] = rdmy; \
26                 } else { \
27                         rbank[i] = (r) + 0x2000 * (i - sb); \
28                 } \
29         } \
30 }
31
32 void PC80S31K::initialize()
33 {
34         DEVICE::initialize();
35         pc80s31k_no_wait = osd->check_feature(_T("PC80S31K_NO_WAIT"));
36         _debug_pc80s31k = osd->check_feature(_T("_DEBUG_PC80S31K"));
37         // init memory
38         memset(rom, 0xff, sizeof(rom));
39         memset(ram, 0, sizeof(ram));
40         memset(rdmy, 0xff, sizeof(rdmy));
41         
42         // load rom image
43         FILEIO* fio = new FILEIO();
44         if(fio->Fopen(create_local_path(_T("PC88.ROM")), FILEIO_READ_BINARY)) {
45                 fio->Fseek(0x14000, FILEIO_SEEK_CUR);
46                 fio->Fread(rom, sizeof(rom), 1);
47                 fio->Fclose();
48         } else if(fio->Fopen(create_local_path(_T("DISK.ROM")), FILEIO_READ_BINARY)) {
49                 fio->Fread(rom, sizeof(rom), 1);
50                 fio->Fclose();
51         } else {
52                 // stop cpu
53                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
54         }
55         delete fio;
56         
57         // init memory map
58         SET_BANK(0x0000, 0x1fff, wdmy, rom);
59         SET_BANK(0x2000, 0x3fff, wdmy, rdmy);
60         SET_BANK(0x4000, 0x7fff, ram, ram);
61         SET_BANK(0x8000, 0xffff, wdmy, rdmy);
62         
63         // XM8 version 1.20
64         // both drives always set force ready signal
65         d_fdc->write_signal(SIG_UPD765A_FREADY, 1, 1);
66 }
67
68 void PC80S31K::reset()
69 {
70         d_fdc->set_drive_type(0, DRIVE_TYPE_2D);
71         d_fdc->set_drive_type(1, DRIVE_TYPE_2D);
72         
73         // clear output
74         d_pio->write_io8(1, 0);
75         d_pio->write_io8(2, 0);
76 }
77
78 uint32_t PC80S31K::read_data8(uint32_t addr)
79 {
80         addr &= 0xffff;
81         return rbank[addr >> 13][addr & 0x1fff];
82 }
83
84 uint32_t PC80S31K::fetch_op(uint32_t addr, int *wait)
85 {
86         addr &= 0xffff;
87 //#ifdef PC80S31K_NO_WAIT
88         if(pc80s31k_no_wait) {
89                 // XM8 version 1.20
90                 // no access wait (both ROM and RAM)
91                 *wait = 0;
92         } else {
93 //#else
94                 *wait = (addr < 0x2000) ? 1 : 0;
95         }
96 //#endif
97         return rbank[addr >> 13][addr & 0x1fff];
98 }
99
100 void PC80S31K::write_data8(uint32_t addr, uint32_t data)
101 {
102         addr &= 0xffff;
103         if(addr == 0x7f15 && data == 0x1f && d_cpu->get_pc() < 0x2000) {
104                 // ugly patch to enable both #1 and #2 drives
105                 data = 0x3f;
106         }
107         wbank[addr >> 13][addr & 0x1fff] = data;
108 }
109
110 uint32_t PC80S31K::read_io8(uint32_t addr)
111 {
112         uint32_t val;
113         
114         switch(addr & 0xff) {
115         case 0xf8:
116                 d_fdc->write_signal(SIG_UPD765A_TC, 1, 1);
117                 break;
118         case 0xfa:
119         case 0xfb:
120                 return d_fdc->read_io8(addr & 1);
121         case 0xfc:
122         case 0xfd:
123                 val = d_pio->read_io8(addr & 3);
124 //#ifdef _DEBUG_PC80S31K
125                 if(_debug_pc80s31k) this->out_debug_log(_T("SUB\tIN RECV(%d)=%2x\n"), addr & 3, val);
126 //#endif
127                 return val;
128         case 0xfe:
129                 val = d_pio->read_io8(addr & 3);
130 //#ifdef _DEBUG_PC80S31K
131                 if(_debug_pc80s31k) {
132                         static uint32_t prev = -1;
133                         if(prev != val) {
134 //                              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);
135                                 prev = val;
136                         }
137                 }
138 //#endif
139                 return val;
140         }
141         return 0xff;
142 }
143
144 void PC80S31K::write_io8(uint32_t addr, uint32_t data)
145 {
146         switch(addr & 0xff) {
147         case 0xf4:
148                 // XM8 version 1.20
149                 // MR/MH/MA/MA2/MA... type ROM only
150                 if(rom[0x7ee] != 0xfe) {
151                         break;
152                 }
153                 for(int drv = 0; drv < 2; drv++) {
154                         uint32_t mode = data >> drv;
155                         if(mode & 1) {
156                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2HD);
157                         } else if(mode & 4) {
158                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2DD);
159                         } else {
160                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2D);
161                         }
162                 }
163                 break;
164         case 0xf7:
165                 // external printer port
166                 break;
167         case 0xf8:
168                 // TODO: we need to update uPD765A to let the motor of each drive on/off
169                 break;
170         case 0xfb:
171                 d_fdc->write_io8(addr & 1, data);
172                 break;
173         case 0xfc:
174         case 0xfd:
175 //#ifdef _DEBUG_PC80S31K
176                 if(_debug_pc80s31k) this->out_debug_log(_T("SUB\tOUT SEND(%d)=%2x\n"), addr & 3, data);
177 //#endif
178                 d_pio->write_io8(addr & 3, data);
179                 break;
180         case 0xfe:
181 //              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);
182                 d_pio->write_io8(addr & 3, data);
183                 break;
184         case 0xff:
185                 if(!(data & 0x80)) {
186                         int bit = (data >> 1) & 7;
187                         if(bit == 4) {
188 //                              this->out_debug_log(_T("SUB\tOUT DAV=%d\n"), data & 1);
189                         } else if(bit == 5) {
190 //                              this->out_debug_log(_T("SUB\tOUT RFD=%d\n"), data & 1);
191                         } else if(bit == 6) {
192 //                              this->out_debug_log(_T("SUB\tOUT DAC=%d\n"), data & 1);
193                         } else if(bit == 7) {
194 //                              this->out_debug_log(_T("SUB\tOUT ATN=%d\n"), data & 1);
195                         }
196                 }
197                 d_pio->write_io8(addr & 3, data);
198                 break;
199         }
200 }
201
202 uint32_t PC80S31K::get_intr_ack()
203 {
204         return 0;       // NOP
205 }
206
207 #define STATE_VERSION   1
208
209 bool PC80S31K::process_state(FILEIO* state_fio, bool loading)
210 {
211
212         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
213                 return false;
214         }
215         if(!state_fio->StateCheckInt32(this_device_id)) {
216                 return false;
217         }
218         state_fio->StateArray(ram, sizeof(ram), 1);
219         return true;
220 }