OSDN Git Service

[VM][FM16BETA][OOPS] Add main feature.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm16beta / main.cpp
1 /*\r
2         FUJITSU FM16beta Emulator 'eFM16beta'\r
3 \r
4         Author : Takeda.Toshiya\r
5         Date   : 2017.12.28-\r
6 \r
7         [ main system ]\r
8 */\r
9 \r
10 #include "main.h"\r
11 #include "sub.h"\r
12 #include "keyboard.h"\r
13 #include "../disk.h"\r
14 #include "../i8237.h"\r
15 #include "../i8259.h"\r
16 #ifdef HAS_I286\r
17 #include "../i286.h"\r
18 #endif\r
19 #include "../mb8877.h"\r
20 #include "../msm58321.h"\r
21 #include "../pcm1bit.h"\r
22 \r
23 void MAIN::initialize()\r
24 {\r
25         MEMORY::initialize();\r
26         \r
27         memset(ram, 0x00, sizeof(ram));\r
28         memset(rom, 0xff, sizeof(rom));\r
29         direct = 0;\r
30         \r
31         read_bios(_T("IPL.ROM"), rom, sizeof(rom));\r
32         \r
33         set_memory_rw(0x00000, 0xfbfff, ram);\r
34         set_memory_r(0xfc000, 0xfffff, rom);\r
35         \r
36         // main-sub\r
37 //      sub_busy = false;\r
38         \r
39         // 1mb fdd\r
40         sidereg_2hd = 0;        // side 0\r
41         drvreg_2hd = 0;         // drive #0, motor on\r
42         drq_2hd = false;\r
43         d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, 1, 1);\r
44         d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, 0, 3);\r
45         \r
46         // 320kb fdd\r
47         sidereg_2d = 0;         // side 0\r
48         drvreg_2d = 0x80;       // drive #0, motor on\r
49         drq_2d = false;\r
50         d_fdc_2d->write_signal(SIG_MB8877_MOTOR, 1, 1);\r
51         d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, 0, 3);\r
52         \r
53         // rtc\r
54         rtc_data = 0;\r
55         \r
56         // irq\r
57         irq_enb = ext_irq_enb = 0;\r
58         irq0_tx = irq0_rx = irq0_syn = irq1 = irq2 = irq3 = irq4 = irq5 = irq6 = irq7 = irq8 = irq9 = false;\r
59         firq0 = firq1 = firq2 = firq3 = false;\r
60         int0 = int1 = int2 = int3 = int4 = int5 = int6 = int7 = false;\r
61 }\r
62 \r
63 void MAIN::release()\r
64 {\r
65         MEMORY::release();\r
66 }\r
67 \r
68 void MAIN::reset()\r
69 {\r
70         MEMORY::reset();\r
71         \r
72 #ifdef HAS_I286\r
73         d_dma->set_address_mask(0x000fffff);\r
74         d_cpu->set_address_mask(0x000fffff);\r
75         rst = 0x00;\r
76 #endif\r
77         \r
78         \r
79         d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 0);\r
80 }\r
81 \r
82 void MAIN::write_io8(uint32_t addr, uint32_t data)\r
83 {\r
84         uint8_t change;\r
85         \r
86         switch(addr) {\r
87         case 0x0020:\r
88                 d_dma->write_signal(SIG_I8237_BANK0, data, 0xff);\r
89                 break;\r
90         case 0x0021:\r
91                 d_dma->write_signal(SIG_I8237_BANK1, data, 0xff);\r
92                 break;\r
93         case 0x0022:\r
94                 d_dma->write_signal(SIG_I8237_BANK2, data, 0xff);\r
95                 break;\r
96         case 0x0023:\r
97                 d_dma->write_signal(SIG_I8237_BANK3, data, 0xff);\r
98                 break;\r
99 \r
100 \r
101 #ifdef HAS_I286\r
102         case 0x0060:\r
103                 if((data & 0xc0) == 0x40) {\r
104                         d_cpu->reset();\r
105                         rst |= 0x01;\r
106                 }\r
107                 if(data & 0x01) {\r
108                         d_dma->set_address_mask(0x00ffffff);\r
109                         d_cpu->set_address_mask(0x00ffffff);\r
110                 } else {\r
111                         d_dma->set_address_mask(0x000fffff);\r
112                         d_cpu->set_address_mask(0x000fffff);\r
113                 }\r
114                 break;\r
115 #endif\r
116         case 0xfd02:\r
117                 change = irq_enb ^ data;\r
118                 irq_enb = data;\r
119                 if(change & 0x01) update_int7();        // Printer\r
120                 if(change & 0x0e) update_int4();        // RS-232C\r
121                 if(change & 0x10) update_int0();        // PTM\r
122                 if(change & 0x20) update_int6();        // 320KB FDD\r
123                 if(change & 0x80) update_int1();        // Keyboard\r
124                 break;\r
125         case 0xfd03:\r
126                 d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x80);\r
127                 break;\r
128 \r
129         case 0xfd04:\r
130                 d_sub->write_signal(SIG_SUB_MAINACK, 1, 1);\r
131                 break;\r
132 \r
133         case 0xfd05:\r
134                 d_sub->write_signal(SIG_SUB_HALT, data, 0x80);\r
135                 d_sub->write_signal(SIG_SUB_CANCEL, data, 0x40);\r
136                 break;\r
137 \r
138         case 0xfd0f:\r
139                 change = direct ^ data;\r
140                 direct = data;\r
141                 if(change & 0x80) {\r
142                         if(direct & 0x80) {\r
143                                 set_memory_mapped_io_rw(0xc0000, 0xcffff, d_sub);\r
144                         } else {\r
145                                 set_memory_rw(0xc0000, 0xcffff, ram + 0xc0000);\r
146                         }\r
147                 }\r
148                 d_keyboard->write_signal(SIG_KEYBOARD_INSLED, data, 0x02);\r
149                 break;\r
150         case 0xfd10:\r
151                 d_rtc->write_signal(SIG_MSM58321_DATA, data, 0x0f);\r
152                 break;\r
153         case 0xfd11:\r
154                 d_rtc->write_signal(SIG_MSM58321_CS, data, 0x80);\r
155                 d_rtc->write_signal(SIG_MSM58321_READ, data, 0x04);\r
156                 d_rtc->write_signal(SIG_MSM58321_WRITE, data, 0x02);\r
157                 d_rtc->write_signal(SIG_MSM58321_ADDR_WRITE, data, 0x01);\r
158                 break;\r
159 \r
160         case 0xfd1c:\r
161                 d_fdc_2d->write_signal(SIG_MB8877_SIDEREG, data, 0x01);\r
162                 sidereg_2d = data;\r
163                 break;\r
164         case 0xfd1d:\r
165                 d_fdc_2d->write_signal(SIG_MB8877_MOTOR, data, 0x80);\r
166                 d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);\r
167                 drvreg_2d = data;\r
168                 break;\r
169 \r
170 \r
171         case 0xfd2c:\r
172                 change = ext_irq_enb ^ data;\r
173                 ext_irq_enb = data;\r
174                 if(change & 0x08) update_int2();        // 1MB FDD\r
175                 break;\r
176 \r
177         case 0xfd34:\r
178                 d_fdc_2hd->write_signal(SIG_MB8877_SIDEREG, data, 0x01);\r
179                 sidereg_2hd = data;\r
180                 break;\r
181         case 0xfd35:\r
182                 d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, ~data, 0x80);\r
183                 d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);\r
184                 drvreg_2hd = data;\r
185                 break;\r
186 \r
187         }\r
188 }\r
189 \r
190 uint32_t MAIN::read_io8(uint32_t addr)\r
191 {\r
192         switch(addr) {\r
193 #ifdef HAS_I286\r
194         case 0x0060:\r
195                 {\r
196                         uint8_t val = rst | (d_cpu->get_shutdown_flag() << 1);\r
197                         rst = 0;\r
198                         d_cpu->set_shutdown_flag(0);\r
199                         return val;\r
200                 }\r
201 #endif\r
202         case 0xfd03:\r
203                 return (irq8 ? 0x01 : 0) | (irq7 ? 0x02 : 0) | (irq4 ? 0x08 : 0) | (irq3 ? 0x10 : 0) | (irq2 ? 0x20 : 0) | (irq1 ? 0x40 : 0) | (irq0_tx || irq0_rx || irq0_syn ? 0x80 : 0);\r
204 \r
205 \r
206         case 0xfd04:\r
207                 return (firq0 ? 0x01 : 0) | (firq1 ? 0x02 : 0) | (firq2 ? 0x80 : 0);\r
208 \r
209         case 0xfd05:\r
210                 return (sub_busy ? 0x80 : 0);\r
211 \r
212         case 0xfd0f:\r
213                 return direct;\r
214 \r
215         case 0xfd10:\r
216                 return rtc_data;\r
217 \r
218         case 0xfd1c:\r
219                 return sidereg_2d;\r
220         case 0xfd1d:\r
221                 return drvreg_2d;\r
222         case 0xfd1f:\r
223                 return (irq4 ? 0x40 : 0) | (drq_2d ? 0x80 : 0);\r
224 \r
225         case 0xfd2c:\r
226                 return (irq6 ? 0x04 : 0) | (irq5 ? 0x40 : 0);\r
227 \r
228         case 0xfd34:\r
229                 return sidereg_2hd;\r
230         case 0xfd35:\r
231                 return drvreg_2hd;\r
232         case 0xfd36:\r
233                 {\r
234                         uint8_t val = 0x40; // DSNS=1\r
235                         if(d_fdc_2hd->read_signal(SIG_MB8877_MOTOR)) {\r
236                                 for(int i = 0; i < 4; i++) {\r
237                                         if(d_fdc_2hd->is_disk_inserted(i)) {\r
238                                                 val |= 1 << i;\r
239                                         }\r
240                                 }\r
241                         }\r
242                         DISK *disk = d_fdc_2hd->get_disk_handler(drvreg_2hd & 3);\r
243                         if(disk->get_rpm() == 300) {\r
244                                 val |= 0x20;\r
245                         }\r
246                         if(disk->inserted && disk->two_side) {\r
247                                 val |= 0x80;\r
248                         }\r
249                         return val;\r
250                 }\r
251         case 0xfd37:\r
252                 return (irq5 ? 0x40 : 0) | (drq_2hd ? 0x80 : 0);\r
253 \r
254 //      case 0xfda0:\r
255 \r
256         }\r
257         return 0xff;\r
258 }\r
259 \r
260 void MAIN::write_signal(int id, uint32_t data, uint32_t mask)\r
261 {\r
262         if(id == SIG_MAIN_IRQ0_TX) {\r
263                 irq0_tx = ((data & mask) != 0);\r
264                 update_int4();\r
265         } else if(id == SIG_MAIN_IRQ0_RX) {\r
266                 irq0_rx = ((data & mask) != 0);\r
267                 update_int4();\r
268         } else if(id == SIG_MAIN_IRQ0_SYN) {\r
269                 irq0_syn = ((data & mask) != 0);\r
270                 update_int4();\r
271         } else if(id == SIG_MAIN_IRQ1) {\r
272                 if(!(irq_enb & 0x80)) {\r
273                         d_sub->write_signal(SIG_SUB_KEY, data, mask);\r
274                 }\r
275                 irq1 = ((data & mask) != 0);\r
276                 update_int1();\r
277         } else if(id == SIG_MAIN_IRQ2) {\r
278                 irq2 = ((data & mask) != 0);\r
279                 update_int5();\r
280         } else if(id == SIG_MAIN_IRQ3) {\r
281                 irq3 = ((data & mask) != 0); // dma\r
282 //              update_int*();\r
283         } else if(id == SIG_MAIN_IRQ4) {\r
284                 irq4 = ((data & mask) != 0);\r
285                 update_int6();\r
286         } else if(id == SIG_MAIN_IRQ5) {\r
287                 irq5 = ((data & mask) != 0);\r
288                 update_int2();\r
289         } else if(id == SIG_MAIN_IRQ6) {\r
290                 irq6 = ((data & mask) != 0);\r
291                 update_int2();\r
292         } else if(id == SIG_MAIN_IRQ7) {\r
293                 irq7 = ((data & mask) != 0);\r
294                 update_int6();\r
295         } else if(id == SIG_MAIN_IRQ8) {\r
296                 irq8 = ((data & mask) != 0);\r
297                 update_int0();\r
298         } else if(id == SIG_MAIN_IRQ9) {\r
299                 irq9 = ((data & mask) != 0);\r
300                 update_int5();\r
301         } else if(id == SIG_MAIN_FIRQ0) {\r
302                 firq0 = ((data & mask) != 0);\r
303                 update_int3();\r
304         } else if(id == SIG_MAIN_FIRQ1) {\r
305                 firq1 = ((data & mask) != 0);\r
306                 update_int1();\r
307         } else if(id == SIG_MAIN_FIRQ2) {\r
308                 firq2 = ((data & mask) != 0);\r
309                 update_int3();\r
310         } else if(id == SIG_MAIN_FIRQ3) {\r
311                 firq3 = ((data & mask) != 0);\r
312                 update_int3();\r
313         } else if(id == SIG_MAIN_SUB_BUSY) {\r
314                 sub_busy = ((data & mask) != 0);\r
315 \r
316 this->out_debug_log(_T("SUB -> MAIN: SUB BUSY = %d\n"), sub_busy);\r
317 \r
318         } else if(id == SIG_MAIN_DRQ_2HD) {\r
319                 drq_2hd = ((data & mask) != 0);\r
320         } else if(id == SIG_MAIN_DRQ_2D) {\r
321                 drq_2d = ((data & mask) != 0);\r
322         } else if(id == SIG_MAIN_RTC_DATA) {\r
323                 rtc_data = (data & mask) | (rtc_data & ~mask);\r
324         } else if(id == SIG_MAIN_RTC_BUSY) {\r
325                 rtc_data = (data & mask) | (rtc_data & ~mask);\r
326         }\r
327 }\r
328 \r
329 /*\r
330 IRQ8                    -> INT0\r
331         IRQ8: \83^\83C\83}\81[\r
332 IRQ1 + FIRQ1            -> INT1\r
333         IRQ1: \83L\81[\83{\81[\83h\r
334         FIRQ1: BREAK\83L\81[\r
335 IRQ5 + IRQ6             -> INT2\r
336         IRQ5: IMB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N\r
337         IRQ6: \83n\81[\83h\83f\83B\83X\83N\r
338 FIRQ0 + FIRQ2 + FIRQ3   -> INT3\r
339         FIRQ0: SUB\83A\83e\83\93\83V\83\87\83\93\r
340         FIRQ2: \8ag\92£\r
341         FIRQ3: \83\86\81[\83U\97p\r
342 IRQ0                    -> INT4\r
343         IRQ0: RS-232C\r
344 IRQ2 + IRQ9 + INTNDP    -> INT5\r
345         IRQ2: \8ag\92£\r
346         IRQ9: \83\86\81[\83U\97p\r
347 IRQ4                    -> INT6\r
348         IRQ4: 320KB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N\r
349 IRQ7                    -> INT7\r
350         IRQ7: \83v\83\8a\83\93\83^\r
351 */\r
352 \r
353 void MAIN::update_int0()\r
354 {\r
355 //      bool prev = int0;\r
356         int0 = (irq8 && (irq_enb & 0x10));\r
357 //      if(prev != int0) {\r
358                 d_pic->write_signal(SIG_I8259_IR0, int0 ? 1 : 0, 1);\r
359 //      }\r
360 }\r
361 \r
362 void MAIN::update_int1()\r
363 {\r
364 //      bool prev = int1;\r
365         int1 = (irq1 && (irq_enb & 0x80)) || firq1;\r
366 //      if(prev != int1) {\r
367                 d_pic->write_signal(SIG_I8259_IR1, int1 ? 1 : 0, 1);\r
368 //      }\r
369 }\r
370 \r
371 void MAIN::update_int2()\r
372 {\r
373 //      bool prev = int2;\r
374         int2 = (irq5 && (ext_irq_enb & 0x08)) || irq6;\r
375 //      if(prev != int2) {\r
376                 d_pic->write_signal(SIG_I8259_IR2, int2 ? 1 : 0, 1);\r
377 //      }\r
378 }\r
379 \r
380 void MAIN::update_int3()\r
381 {\r
382 //      bool prev = int3;\r
383         int3 = firq0 || firq2 || firq3;\r
384 //      if(prev != int3) {\r
385                 d_pic->write_signal(SIG_I8259_IR3, int3 ? 1 : 0, 1);\r
386 //      }\r
387 }\r
388 \r
389 void MAIN::update_int4()\r
390 {\r
391 //      bool prev = int4;\r
392         int4 = (irq0_tx && (irq_enb & 0x02)) || (irq0_rx && (irq_enb & 0x04)) || (irq0_syn && (irq_enb & 0x08));\r
393 //      if(prev != int4) {\r
394                 d_pic->write_signal(SIG_I8259_IR4, int4 ? 1 : 0, 1);\r
395 //      }\r
396 }\r
397 \r
398 void MAIN::update_int5()\r
399 {\r
400 //      bool prev = int5;\r
401         int5 = irq2 || irq9;\r
402 //      if(prev != int5) {\r
403                 d_pic->write_signal(SIG_I8259_IR5, int5 ? 1 : 0, 1);\r
404 //      }\r
405 }\r
406 \r
407 void MAIN::update_int6()\r
408 {\r
409 //      bool prev = int6;\r
410         int6 = (irq6 && (irq_enb & 0x20));\r
411 //      if(prev != int6) {\r
412                 d_pic->write_signal(SIG_I8259_IR6, int6 ? 1 : 0, 1);\r
413 //      }\r
414 }\r
415 \r
416 void MAIN::update_int7()\r
417 {\r
418 //      bool prev = int7;\r
419         int7 = irq7 && (irq_enb & 0x01);\r
420 //      if(prev != int7) {\r
421                 d_pic->write_signal(SIG_I8259_IR7, int7 ? 1 : 0, 1);\r
422 //      }\r
423 }\r
424 \r
425 #define STATE_VERSION   1\r
426 \r
427 bool MAIN::process_state(FILEIO* state_fio, bool loading)\r
428 {\r
429         if(!state_fio->StateCheckUint32(STATE_VERSION)) {\r
430                 return false;\r
431         }\r
432         if(!state_fio->StateCheckInt32(this_device_id)) {\r
433                 return false;\r
434         }\r
435         return true;\r
436 }\r
437 \r