OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc9801 / floppy.cpp
1 /*
2         NEC PC-9801 Emulator 'ePC-9801'
3         NEC PC-9801E/F/M Emulator 'ePC-9801E'
4         NEC PC-9801U Emulator 'ePC-9801U'
5         NEC PC-9801VF Emulator 'ePC-9801VF'
6         NEC PC-9801VM Emulator 'ePC-9801VM'
7         NEC PC-9801VX Emulator 'ePC-9801VX'
8         NEC PC-9801RA Emulator 'ePC-9801RA'
9         NEC PC-98XA Emulator 'ePC-98XA'
10         NEC PC-98XL Emulator 'ePC-98XL'
11         NEC PC-98RL Emulator 'ePC-98RL'
12         NEC PC-98DO Emulator 'ePC-98DO'
13
14         Author : Takeda.Toshiya
15         Date   : 2010.09.15-
16
17         [ floppy ]
18 */
19
20 #include "floppy.h"
21 #include "../disk.h"
22 #include "../i8237.h"
23 #include "../i8259.h"
24 #include "../upd765a.h"
25
26 #define EVENT_TIMER     0
27
28 namespace PC9801 {
29
30 void FLOPPY::reset()
31 {
32 #if defined(SUPPORT_2HD_FDD_IF)
33         for(int i = 0; i < MAX_DRIVE; i++) {
34                 d_fdc_2hd->set_drive_type(i, DRIVE_TYPE_2HD);
35         }
36         ctrlreg_2hd = 0x80;
37 #endif
38 #if defined(SUPPORT_2DD_FDD_IF)
39         for(int i = 0; i < MAX_DRIVE; i++) {
40                 d_fdc_2dd->set_drive_type(i, DRIVE_TYPE_2DD);
41         }
42         ctrlreg_2dd = 0x80;
43 #endif
44 #if defined(SUPPORT_2HD_2DD_FDD_IF)
45         for(int i = 0; i < 4; i++) {
46                 d_fdc->set_drive_type(i, DRIVE_TYPE_2HD);
47         }
48         ctrlreg = 0x80;
49         modereg = 0x03;
50 #endif
51         timer_id = -1;
52 }
53
54 void FLOPPY::write_io8(uint32_t addr, uint32_t data)
55 {
56         switch(addr) {
57 #if defined(SUPPORT_2HD_FDD_IF)
58         case 0x0090:
59                 d_fdc_2hd->write_io8(0, data);
60                 break;
61         case 0x0092:
62                 d_fdc_2hd->write_io8(1, data);
63                 break;
64         case 0x0094:
65         case 0x0096:
66                 if(!(ctrlreg_2hd & 0x80) && (data & 0x80)) {
67                         d_fdc_2hd->reset();
68                 }
69                 d_fdc_2hd->write_signal(SIG_UPD765A_FREADY, data, 0x40);
70                 ctrlreg_2hd = data;
71                 break;
72 #endif
73 #if defined(SUPPORT_2DD_FDD_IF)
74         case 0x00c8:
75                 d_fdc_2dd->write_io8(0, data);
76                 break;
77         case 0x00ca:
78                 d_fdc_2dd->write_io8(1, data);
79                 break;
80         case 0x00cc:
81         case 0x00ce:
82                 if(!(ctrlreg_2dd & 0x80) && (data & 0x80)) {
83                         d_fdc_2dd->reset();
84                 }
85                 if(data & 1) {
86                         if(timer_id != -1) {
87                                 cancel_event(this, timer_id);
88                         }
89                         register_event(this, EVENT_TIMER, 100000, false, &timer_id);
90                 }
91                 d_fdc_2dd->write_signal(SIG_UPD765A_MOTOR, data, 0x08);
92                 ctrlreg_2dd = data;
93                 break;
94 #endif
95 #if defined(SUPPORT_2HD_2DD_FDD_IF)
96         case 0x0090:
97 #if !defined(SUPPORT_HIRESO)
98         case 0x00c8:
99                 if(((addr >> 4) & 1) == (modereg & 1))
100 #endif
101                 {
102                         d_fdc->write_io8(0, data);
103                 }
104                 break;
105         case 0x0092:
106 #if !defined(SUPPORT_HIRESO)
107         case 0x00ca:
108                 if(((addr >> 4) & 1) == (modereg & 1))
109 #endif
110                 {
111                         d_fdc->write_io8(1, data);
112                 }
113                 break;
114         case 0x0094:
115         case 0x0096:
116 #if !defined(SUPPORT_HIRESO)
117         case 0x00cc:
118         case 0x00ce:
119                 if(((addr >> 4) & 1) == (modereg & 1))
120 #endif
121                 {
122                         if(!(ctrlreg & 0x80) && (data & 0x80)) {
123                                 d_fdc->reset();
124                         }
125 #if !defined(SUPPORT_HIRESO)
126                         if(!(addr == 0xcc && !(data & 0x20)))
127 #endif
128                         {
129                                 d_fdc->write_signal(SIG_UPD765A_FREADY, data, 0x40);
130                         }
131 #if defined(SUPPORT_HIRESO)
132                         if((ctrlreg & 0x20) && !(data & 0x20)) {
133                                 d_fdc->set_drive_type(0, DRIVE_TYPE_2HD);
134                                 d_fdc->set_drive_type(1, DRIVE_TYPE_2HD);
135                         } else if(!(ctrlreg & 0x20) && (data & 0x20)) {
136                                 d_fdc->set_drive_type(0, DRIVE_TYPE_2DD);
137                                 d_fdc->set_drive_type(1, DRIVE_TYPE_2DD);
138                         }
139 #endif
140 //#if !defined(_PC98XA) && !defined(_PC98XL)
141 //                      if(modereg & 0x04) {
142 //                              d_fdc->write_signal(SIG_UPD765A_MOTOR, data, 0x08);
143 //                      }
144                         if(data & 0x01) {
145                                 if(timer_id != -1) {
146                                         cancel_event(this, timer_id);
147                                 }
148                                 register_event(this, EVENT_TIMER, 100000, false, &timer_id);
149                         }
150                         ctrlreg = data;
151 //#endif
152                 }
153                 break;
154         case 0x00be:
155 #if !defined(SUPPORT_HIRESO)
156                 if(!(modereg & 2) && (data & 2)) {
157                         d_fdc->set_drive_type(0, DRIVE_TYPE_2HD);
158                         d_fdc->set_drive_type(1, DRIVE_TYPE_2HD);
159                 } else if((modereg & 2) && !(data & 2)) {
160                         d_fdc->set_drive_type(0, DRIVE_TYPE_2DD);
161                         d_fdc->set_drive_type(1, DRIVE_TYPE_2DD);
162                 }
163 #endif
164                 modereg = data;
165                 break;
166 #endif
167         }
168 }
169
170 uint32_t FLOPPY::read_io8(uint32_t addr)
171 {
172         uint32_t value = 0;
173         
174         switch(addr) {
175 #if defined(SUPPORT_2HD_FDD_IF)
176         case 0x0090:
177                 return d_fdc_2hd->read_io8(0);
178         case 0x0092:
179                 return d_fdc_2hd->read_io8(1);
180         case 0x0094:
181         case 0x0096:
182 //              value |= 0x80; // FINT1 (DIP SW 1-7), 1 = OFF, 0 = ON
183                 value |= 0x40; // FINT0 (DIP SW 1-6), 1 = OFF, 0 = ON
184 //              value |= 0x20; // DMACH (DIP SW 1-3), 1 = OFF, 0 = ON
185                 return value;
186 #endif
187 #if defined(SUPPORT_2DD_FDD_IF)
188         case 0x00c8:
189                 return d_fdc_2dd->read_io8(0);
190         case 0x00ca:
191                 return d_fdc_2dd->read_io8(1);
192         case 0x00cc:
193         case 0x00ce:
194 //              value |= 0x80; // FINT1 (DIP SW 1-7), 1 = OFF, 0 = ON
195                 value |= 0x40; // FINT0 (DIP SW 1-6), 1 = OFF, 0 = ON
196                 value |= 0x20; // DMACH (DIP SW 1-3), 1 = OFF, 0 = ON
197                 if(d_fdc_2dd->is_disk_inserted()) {
198                         value |= 0x10; // RDY
199                 }
200                 return value;
201 #endif
202 #if defined(SUPPORT_2HD_2DD_FDD_IF)
203         case 0x0090:
204 #if !defined(SUPPORT_HIRESO)
205         case 0x00c8:
206                 if(((addr >> 4) & 1) == (modereg & 1))
207 #endif
208                 {
209                         return d_fdc->read_io8(0);
210                 }
211                 break;
212         case 0x0092:
213 #if !defined(SUPPORT_HIRESO)
214         case 0x00ca:
215                 if(((addr >> 4) & 1) == (modereg & 1))
216 #endif
217                 {
218                         return d_fdc->read_io8(1);
219                 }
220                 break;
221         case 0x0094:
222         case 0x0096:
223 #if !defined(SUPPORT_HIRESO)
224                 if(modereg & 1) {
225 //                      value |= 0x80; // FINT1 (DIP SW 1-7), 1 = OFF, 0 = ON
226                         value |= 0x40; // FINT0 (DIP SW 1-6), 1 = OFF, 0 = ON
227 //                      value |= 0x20; // DMACH (DIP SW 1-3), 1 = OFF, 0 = ON
228 //                      value |= 0x08; // TYP1,0 (DIP SW 1-4), 1,0 = ON  Internal FDD: #3,#4, External FDD: #1,#2
229                         value |= 0x04; // TYP1,0 (DIP SW 1-4), 0,1 = OFF Internal FDD: #1,#2, External FDD: #3,#4
230                         return value;
231                 }
232 #else
233 //              value |= 0x80; // MODE, 0 = Internal FDD existing
234                 value |= ctrlreg & 0x20; // High Density, 1 = 640KB, 0 = 1MB
235                 return value;
236 #endif
237                 break;
238 #if !defined(SUPPORT_HIRESO)
239         case 0x00be:
240                 return 0xf8 | (modereg & 3);
241         case 0x00cc:
242         case 0x00ce:
243                 if(!(modereg & 1)) {
244 //                      value |= 0x80; // FINT1 (DIP SW 1-7), 1 = OFF, 0 = ON
245                         value |= 0x40; // FINT0 (DIP SW 1-6), 1 = OFF, 0 = ON
246                         value |= 0x20; // DMACH (DIP SW 1-3), 1 = OFF, 0 = ON
247 //                      value |= 0x08; // TYP1,0 (DIP SW 1-4), 1,0 = ON  Internal FDD: #3,#4, External FDD: #1,#2
248                         value |= 0x04; // TYP1,0 (DIP SW 1-4), 0,1 = OFF Internal FDD: #1,#2, External FDD: #3,#4
249                         if(d_fdc->is_disk_inserted()) {
250                                 value |= 0x10; // RDY
251                         }
252                         return value;
253                 }
254                 break;
255 #endif
256 #endif
257         }
258         return 0xff;//addr & 0xff;
259 }
260
261 void FLOPPY::write_signal(int id, uint32_t data, uint32_t mask)
262 {
263         switch(id) {
264 #if defined(SUPPORT_2HD_FDD_IF)
265         case SIG_FLOPPY_2HD_IRQ:
266                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR3, data, mask);
267                 break;
268         case SIG_FLOPPY_2HD_DRQ:
269                 d_dma->write_signal(SIG_I8237_CH2, data, mask);
270                 break;
271 #endif
272 #if defined(SUPPORT_2DD_FDD_IF)
273         case SIG_FLOPPY_2DD_IRQ:
274                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
275                 break;
276         case SIG_FLOPPY_2DD_DRQ:
277                 d_dma->write_signal(SIG_I8237_CH3, data, mask);
278                 break;
279 #endif
280 #if defined(SUPPORT_2HD_2DD_FDD_IF)
281         case SIG_FLOPPY_IRQ:
282 #if !defined(SUPPORT_HIRESO)
283                 if(modereg & 1) {
284                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR3, data, mask);
285                 } else {
286                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
287                 }
288 #else
289                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR3, data, mask);
290 #endif
291                 break;
292         case SIG_FLOPPY_DRQ:
293 #if !defined(SUPPORT_HIRESO)
294                 if(modereg & 1) {
295                         d_dma->write_signal(SIG_I8237_CH2, data, mask);
296                 } else {
297                         d_dma->write_signal(SIG_I8237_CH3, data, mask);
298                 }
299 #else
300                 d_dma->write_signal(SIG_I8237_CH1, data, mask);
301 #endif
302                 break;
303 #endif
304         }
305 }
306
307 void FLOPPY::event_callback(int event_id, int err)
308 {
309 #if defined(SUPPORT_2DD_FDD_IF)
310         if(ctrlreg_2dd & 4) {
311                 write_signal(SIG_FLOPPY_2DD_IRQ, 1, 1);
312         }
313 #endif
314 #if defined(SUPPORT_2HD_2DD_FDD_IF)
315         if(ctrlreg & 4) {
316                 write_signal(SIG_FLOPPY_IRQ, 1, 1);
317         }
318 #endif
319         timer_id = -1;
320 }
321
322 #define STATE_VERSION   1
323
324 bool FLOPPY::process_state(FILEIO* state_fio, bool loading)
325 {
326         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
327                 return false;
328         }
329         if(!state_fio->StateCheckInt32(this_device_id)) {
330                 return false;
331         }
332 #if defined(SUPPORT_2HD_FDD_IF)
333         state_fio->StateUint8(ctrlreg_2hd);
334 #endif
335 #if defined(SUPPORT_2DD_FDD_IF)
336         state_fio->StateUint8(ctrlreg_2dd);
337 #endif
338 #if defined(SUPPORT_2HD_2DD_FDD_IF)
339         state_fio->StateUint8(ctrlreg);
340         state_fio->StateUint8(modereg);
341 #endif
342         state_fio->StateInt32(timer_id);
343         return true;
344 }
345
346 }