OSDN Git Service

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