OSDN Git Service

[General][Qt] Merge upstream 2015-03-15.
[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-98DO Emulator 'ePC-98DO'
5
6         Author : Takeda.Toshiya
7         Date   : 2010.09.15-
8
9         [ floppy ]
10 */
11
12 #include "floppy.h"
13 #include "../disk.h"
14 #include "../i8237.h"
15 #include "../i8259.h"
16 #include "../upd765a.h"
17
18 #define EVENT_TIMER     0
19
20 void FLOPPY::reset()
21 {
22 #if defined(SUPPORT_2HD_FDD_IF)
23         for(int i = 0; i < MAX_DRIVE; i++) {
24                 d_fdc_2hd->set_drive_type(i, DRIVE_TYPE_2HD);
25         }
26         ctrlreg_2hd = 0x80;
27 #endif
28 #if defined(SUPPORT_2DD_FDD_IF)
29         for(int i = 0; i < MAX_DRIVE; i++) {
30                 d_fdc_2dd->set_drive_type(i, DRIVE_TYPE_2DD);
31         }
32         ctrlreg_2dd = 0x80;
33 #endif
34 #if defined(SUPPORT_2HD_2DD_FDD_IF)
35         for(int i = 0; i < 4; i++) {
36                 d_fdc->set_drive_type(i, DRIVE_TYPE_2HD);
37         }
38         ctrlreg = 0x80;
39         modereg = 0x03;
40 #endif
41         timer_id = -1;
42 }
43
44 void FLOPPY::write_io8(uint32 addr, uint32 data)
45 {
46         switch(addr & 0xffff) {
47 #if defined(SUPPORT_2HD_FDD_IF)
48         case 0x90:
49                 d_fdc_2hd->write_io8(0, data);
50                 break;
51         case 0x92:
52                 d_fdc_2hd->write_io8(1, data);
53                 break;
54         case 0x94:
55                 if(!(ctrlreg_2hd & 0x80) && (data & 0x80)) {
56                         d_fdc_2hd->reset();
57                 }
58                 d_fdc_2hd->write_signal(SIG_UPD765A_FREADY, data, 0x40);
59                 ctrlreg_2hd = data;
60                 break;
61 #endif
62 #if defined(SUPPORT_2DD_FDD_IF)
63         case 0xc8:
64                 d_fdc_2dd->write_io8(0, data);
65                 break;
66         case 0xca:
67                 d_fdc_2dd->write_io8(1, data);
68                 break;
69         case 0xcc:
70                 if(!(ctrlreg_2dd & 0x80) && (data & 0x80)) {
71                         d_fdc_2dd->reset();
72                 }
73                 if(data & 1) {
74                         if(timer_id != -1) {
75                                 cancel_event(this, timer_id);
76                         }
77                         register_event(this, EVENT_TIMER, 100000, false, &timer_id);
78                 }
79                 d_fdc_2dd->write_signal(SIG_UPD765A_MOTOR, data, 0x08);
80                 ctrlreg_2dd = data;
81                 break;
82 #endif
83 #if defined(SUPPORT_2HD_2DD_FDD_IF)
84         case 0x90:
85         case 0xc8:
86                 if(((addr >> 4) & 1) == (modereg & 1)) {
87                         d_fdc->write_io8(0, data);
88                 }
89                 break;
90         case 0x92:
91         case 0xca:
92                 if(((addr >> 4) & 1) == (modereg & 1)) {
93                         d_fdc->write_io8(1, data);
94                 }
95                 break;
96         case 0x94:
97         case 0xcc:
98                 if(((addr >> 4) & 1) == (modereg & 1)) {
99                         if(!(ctrlreg & 0x80) && (data & 0x80)) {
100                                 d_fdc->reset();
101                         }
102                         if(!(addr == 0xcc && !(data & 0x20))) {
103                                 d_fdc->write_signal(SIG_UPD765A_FREADY, data, 0x40);
104                         }
105                         if(data & 1) {
106                                 if(timer_id != -1) {
107                                         cancel_event(this, timer_id);
108                                 }
109                                 register_event(this, EVENT_TIMER, 100000, false, &timer_id);
110                         }
111 //                      if(modereg & 4) {
112 //                              d_fdc->write_signal(SIG_UPD765A_MOTOR, data, 0x08);
113 //                      }
114                         ctrlreg = data;
115                 }
116                 break;
117         case 0xbe:
118                 if(!(modereg & 2) && (data & 2)) {
119                         d_fdc->set_drive_type(0, DRIVE_TYPE_2HD);
120                         d_fdc->set_drive_type(1, DRIVE_TYPE_2HD);
121                 } else if((modereg & 2) && !(data & 2)) {
122                         d_fdc->set_drive_type(0, DRIVE_TYPE_2DD);
123                         d_fdc->set_drive_type(1, DRIVE_TYPE_2DD);
124                 }
125                 modereg = data;
126                 break;
127 #endif
128         }
129 }
130
131 uint32 FLOPPY::read_io8(uint32 addr)
132 {
133         switch(addr & 0xffff) {
134 #if defined(SUPPORT_2HD_FDD_IF)
135         case 0x90:
136                 return d_fdc_2hd->read_io8(0);
137         case 0x92:
138                 return d_fdc_2hd->read_io8(1);
139 #if !defined(_PC9801)
140         case 0x94:
141                 return 0x5f;    // 0x40 ???
142 #endif
143 #endif
144 #if defined(SUPPORT_2DD_FDD_IF)
145         case 0xc8:
146                 return d_fdc_2dd->read_io8(0);
147         case 0xca:
148                 return d_fdc_2dd->read_io8(1);
149         case 0xcc:
150                 return (d_fdc_2dd->disk_inserted() ? 0x10 : 0) | 0x6f;  // 0x60 ???
151 #endif
152 #if defined(SUPPORT_2HD_2DD_FDD_IF)
153         case 0x90:
154         case 0xc8:
155                 if(((addr >> 4) & 1) == (modereg & 1)) {
156                         return d_fdc->read_io8(0);
157                 }
158                 break;
159         case 0x92:
160         case 0xca:
161                 if(((addr >> 4) & 1) == (modereg & 1)) {
162                         return d_fdc->read_io8(1);
163                 }
164                 break;
165         case 0x94:
166                 if(modereg & 1) {
167                         return 0x44;
168                 }
169                 break;
170         case 0xbe:
171                 return 0xf8 | (modereg & 3);
172         case 0xcc:
173                 if(!(modereg & 1)) {
174                         return (d_fdc->disk_inserted() ? 0x10 : 0) | 0x64;      // 0x60 ???
175                 }
176                 break;
177 #endif
178         }
179         return 0xff;//addr & 0xff;
180 }
181
182 void FLOPPY::write_signal(int id, uint32 data, uint32 mask)
183 {
184         switch(id) {
185 #if defined(SUPPORT_2HD_FDD_IF)
186         case SIG_FLOPPY_2HD_IRQ:
187                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR3, data, mask);
188                 break;
189         case SIG_FLOPPY_2HD_DRQ:
190                 d_dma->write_signal(SIG_I8237_CH2, data, mask);
191                 break;
192 #endif
193 #if defined(SUPPORT_2DD_FDD_IF)
194         case SIG_FLOPPY_2DD_IRQ:
195                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
196                 break;
197         case SIG_FLOPPY_2DD_DRQ:
198                 d_dma->write_signal(SIG_I8237_CH3, data, mask);
199                 break;
200 #endif
201 #if defined(SUPPORT_2HD_2DD_FDD_IF)
202         case SIG_FLOPPY_IRQ:
203                 if(modereg & 1) {
204                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR3, data, mask);
205                 } else {
206                         d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
207                 }
208                 break;
209         case SIG_FLOPPY_DRQ:
210                 if(modereg & 1) {
211                         d_dma->write_signal(SIG_I8237_CH2, data, mask);
212                 } else {
213                         d_dma->write_signal(SIG_I8237_CH3, data, mask);
214                 }
215                 break;
216 #endif
217         }
218 }
219
220 void FLOPPY::event_callback(int event_id, int err)
221 {
222 #if defined(SUPPORT_2DD_FDD_IF)
223         if(ctrlreg_2dd & 4) {
224                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, 1, 1);
225         }
226 #endif
227 #if defined(SUPPORT_2HD_2DD_FDD_IF)
228         if(ctrlreg & 4) {
229                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, 1, 1);
230         }
231 #endif
232         timer_id = -1;
233 }
234
235
236 #define STATE_VERSION   1
237
238 void FLOPPY::save_state(FILEIO* state_fio)
239 {
240         state_fio->FputUint32(STATE_VERSION);
241         state_fio->FputInt32(this_device_id);
242         
243 #if defined(SUPPORT_2HD_FDD_IF)
244         state_fio->FputUint8(ctrlreg_2hd);
245 #endif
246 #if defined(SUPPORT_2DD_FDD_IF)
247         state_fio->FputUint8(ctrlreg_2dd);
248 #endif
249 #if defined(SUPPORT_2HD_2DD_FDD_IF)
250         state_fio->FputUint8(ctrlreg);
251         state_fio->FputUint8(modereg);
252 #endif
253         state_fio->FputInt32(timer_id);
254 }
255
256 bool FLOPPY::load_state(FILEIO* state_fio)
257 {
258         if(state_fio->FgetUint32() != STATE_VERSION) {
259                 return false;
260         }
261         if(state_fio->FgetInt32() != this_device_id) {
262                 return false;
263         }
264 #if defined(SUPPORT_2HD_FDD_IF)
265         ctrlreg_2hd = state_fio->FgetUint8();
266 #endif
267 #if defined(SUPPORT_2DD_FDD_IF)
268         ctrlreg_2dd = state_fio->FgetUint8();
269 #endif
270 #if defined(SUPPORT_2HD_2DD_FDD_IF)
271         ctrlreg = state_fio->FgetUint8();
272         modereg = state_fio->FgetUint8();
273 #endif
274         timer_id = state_fio->FgetInt32();
275         return true;
276 }
277