OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz3500 / main.cpp
1 /*
2         SHARP MZ-3500 Emulator 'EmuZ-3500'
3
4         Author : Takeda.Toshiya
5         Date   : 2010.08.31-
6
7         [ main pcb ]
8 */
9
10 #include "./main.h"
11 #include "../upd765a.h"
12
13 namespace MZ3500 {
14
15 #define SET_BANK(s, e, w, r) { \
16         int sb = (s) >> 11, eb = (e) >> 11; \
17         for(int i = sb; i <= eb; i++) { \
18                 if((w) == wdmy) { \
19                         wbank[i] = wdmy; \
20                 } else { \
21                         wbank[i] = (w) + 0x800 * (i - sb); \
22                 } \
23                 if((r) == rdmy) { \
24                         rbank[i] = rdmy; \
25                 } else { \
26                         rbank[i] = (r) + 0x800 * (i - sb); \
27                 } \
28         } \
29 }
30
31 void MAIN::initialize()
32 {
33         // init memory
34         memset(ipl, 0xff, sizeof(ipl));
35         memset(ram, 0, sizeof(ram));
36         memset(common, 0, sizeof(common));
37         memset(basic, 0xff, sizeof(basic));
38         memset(ext, 0xff, sizeof(ext));
39         memset(rdmy, 0xff, sizeof(rdmy));
40         
41         // load rom images
42         FILEIO* fio = new FILEIO();
43         if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
44                 fio->Fread(ipl, sizeof(ipl), 1);
45                 fio->Fclose();
46         }
47         if(fio->Fopen(create_local_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {
48                 fio->Fread(basic, sizeof(basic), 1);
49                 fio->Fclose();
50         }
51         if(fio->Fopen(create_local_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
52                 fio->Fread(ext, sizeof(ext), 1);
53                 fio->Fclose();
54         }
55         delete fio;
56         
57         crt_400line = (config.monitor_type == 0 || config.monitor_type == 1);
58 }
59
60 void MAIN::reset()
61 {
62         // memory mapper
63         ms = ma = mo = 0;
64         me1 = me2 = false;
65         update_bank();
66         
67         // sub cpu
68         srqb = 2;
69         sres = 0;
70         sack = true;
71         srdy = false;
72         
73         // interrupt
74         intfd = int0 = int1 = int2 = int3 = int4 = false;
75         me = e1 = false;
76         inp = 0;
77         
78         // mfd
79         drq = index = false;
80 }
81
82 void MAIN::write_data8(uint32_t addr, uint32_t data)
83 {
84         addr &= 0xffff;
85         wbank[addr >> 11][addr & 0x7ff] = data;
86 }
87
88 uint32_t MAIN::read_data8(uint32_t addr)
89 {
90         addr &= 0xffff;
91         return rbank[addr >> 11][addr & 0x7ff];
92 }
93
94 uint32_t MAIN::fetch_op(uint32_t addr, int *wait)
95 {
96         // mz3500sm p.23
97         *wait = 1;
98         return read_data8(addr);
99 }
100
101 void MAIN::write_io8(uint32_t addr, uint32_t data)
102 {
103         switch(addr & 0xff) {
104         case 0xec:      // mz3500sm p.17
105         case 0xed:
106         case 0xee:
107         case 0xef:
108                 if(int0) {
109                         int0 = false;
110                         update_irq();
111                 }
112                 break;
113         case 0xf8:      // mz3500sm p.59
114         case 0xfa:
115                 if(data & 0x40) {
116                         for(int i = 0; i < 3; i++) {
117                                 if(data & (1 << i)) {
118 //                                      this->out_debug_log(_T("MAIN->FDC\tDRIVE=%d\n"), i);
119                                         d_fdc->write_signal(SIG_UPD765A_DRVSEL, i, 3);
120                                         break;
121                                 }
122                         }
123                 }
124                 d_fdc->write_signal(SIG_UPD765A_MOTOR, data, 0x10);
125                 d_fdc->write_signal(SIG_UPD765A_TC, data, 0x20);
126                 motor = ((data & 0x10) != 0);
127                 {
128                         bool new_me = ((data & 0x80) != 0);
129                         if(me != new_me) {
130                                 me = new_me;
131                                 update_irq();
132                         }
133                 }
134                 break;
135         case 0xf9:      // mz3500sm p.59
136         case 0xfb:
137                 d_fdc->write_dma_io8(1, data);
138                 break;
139         case 0xfc:      // mz3500sm p.23
140                 if((srqb & 2) != (data & 2)) {
141 //                      this->out_debug_log(_T("MAIN->SUB\tBUSREQ=%d\n"), (data&2)?1:0);
142                         d_subcpu->write_signal(SIG_CPU_BUSREQ, data, 2);
143                 }
144                 srqb = data;
145                 {
146                         bool new_e1 = ((data & 1) != 0);
147                         if(e1 != new_e1) {
148                                 e1 = new_e1;
149                                 update_irq();
150                         }
151                 }
152                 break;
153         case 0xfd:      // mz3500sm p.23
154                 if(!(sres & 0x80) && (data & 0x80)) {
155 //                      this->out_debug_log(_T("MAIN->SUB\tRESET\n"));
156                         d_subcpu->reset();
157                 }
158                 sres = data;
159                 {
160                         uint8_t new_ms = data & 3;
161                         if(ms != new_ms) {
162                                 ms = new_ms;
163                                 update_bank();
164                         }
165                 }
166                 break;
167         case 0xfe:      // mz3500sm p.23
168                 {
169                         uint8_t new_mo = data & 7;
170                         uint8_t new_ma = (data >> 4) & 0x0f;
171                         if(mo != new_mo || ma != new_ma) {
172                                 mo = new_mo;
173                                 ma = new_ma;
174                                 update_bank();
175                         }
176                 }
177                 break;
178         case 0xff:      // mz3500sm p.23
179                 {
180                         bool new_me1 = ((data & 1) != 0);
181                         bool new_me2 = ((data & 2) != 0);
182                         if(me1 != new_me1 || me2 != new_me2) {
183                                 me1 = new_me1;
184                                 me2 = new_me2;
185                                 update_bank();
186                         }
187                 }
188                 break;
189         }
190 }
191
192 uint32_t MAIN::read_io8(uint32_t addr)
193 {
194         uint32_t val = 0xff;
195         
196         switch(addr & 0xff) {
197         case 0xec:      // mz3500sm p.17
198         case 0xed:
199         case 0xee:
200         case 0xef:
201                 if(int0) {
202                         int0 = false;
203                         update_irq();
204                 }
205                 break;
206         case 0xf8:      // mz3500sm p.59
207         case 0xfa:
208                 return 0xf8 | (drq ? 1 : 0) | (index ? 2 : 0) | (motor ? 4 : 0);
209         case 0xf9:      // mz3500sm p.59
210         case 0xfb:
211                 return d_fdc->read_dma_io8(1);
212         case 0xfc:      // mz3500sm p.23
213                 return srqb;
214         case 0xfd:      // mz3500sm p.23
215                 return sres;
216         case 0xfe:      // mz3500sm p.23,85-86
217                 // bit4: sw4=on,  select period for decimal point
218                 // bit3: sw3=on,  select hiresolution crt
219                 // bit2: sw2=off, select MZ-1P02
220                 // bit1: sw1=on
221                 // bit0: sec=on,  select double side mini floppy
222                 return 0xe0 | (((~config.dipswitch) & 0x0b) << 1) | (crt_400line ? 0 : 8);
223         case 0xff:      // mz3500sm p.23,85-86
224                 // bit7: fd3=off, select double side mini floppy
225                 // bit6: fd2=off, select double side mini floppy
226                 // bit5: fd1=off, normally small letter and in capital letter when shifted
227                 return 0xc0 | ((config.dipswitch & 0x80) ? 0 : 0x20) | (srdy ? 0x10 : 0) | (sack ? 0 : 8) | (inp & 7);
228         }
229         return 0xff;
230 }
231
232 void MAIN::write_signal(int id, uint32_t data, uint32_t mask)
233 {
234         if(id == SIG_MAIN_SACK) {
235                 sack = ((data & mask) != 0);
236 //              this->out_debug_log(_T("SUB->MAIN\tSACK=%d\n"), sack?1:0);
237         } else if(id == SIG_MAIN_SRDY) {
238                 srdy = ((data & mask) != 0);
239 //              this->out_debug_log(_T("SUB->MAIN\tSRDY=%d\n"), srdy?1:0);
240         } else if(id == SIG_MAIN_INTFD) {
241                 intfd = ((data & mask) != 0);
242 //              this->out_debug_log(_T("FDC->MAIN\tINTFD=%d\n"), intfd?1:0);
243                 update_irq();
244         } else if(id == SIG_MAIN_INT0) {
245                 int0 = ((data & mask) != 0);
246 //              this->out_debug_log(_T("SUB->MAIN\tINT0=%d\n"), int0?1:0);
247                 update_irq();
248         } else if(id == SIG_MAIN_INT1) {
249                 int1 = ((data & mask) != 0);
250                 update_irq();
251         } else if(id == SIG_MAIN_INT2) {
252                 int2 = ((data & mask) != 0);
253                 update_irq();
254         } else if(id == SIG_MAIN_INT3) {
255                 int3 = ((data & mask) != 0);
256                 update_irq();
257         } else if(id == SIG_MAIN_INT4) {
258                 int4 = ((data & mask) != 0);
259                 update_irq();
260         } else if(id == SIG_MAIN_DRQ) {
261                 drq = ((data & mask) != 0);
262         } else if(id == SIG_MAIN_INDEX) {
263                 index = ((data & mask) != 0);
264         }
265 }
266
267 void MAIN::update_irq()
268 {
269         bool next = false;
270         
271         if(intfd && me) {
272                 intfd = false;
273                 inp = 0;
274                 next = true;
275         } else if(e1) {
276                 if(int0) {
277                         inp = 1;
278                         next = true;
279                 } else if(int1) {
280                         inp = 2;
281                         next = true;
282                 } else if(int2) {
283                         inp = 3;
284                         next = true;
285                 } else if(int3) {
286                         inp = 4;
287                         next = true;
288                 } else if(int4) {
289                         inp = 5;
290                         next = true;
291                 }
292         }
293         if(next) {
294 //              this->out_debug_log(_T("MAIN IRQ=%d SRC=%d\n"), next?1:0,inp);
295                 d_maincpu->set_intr_line(true, true, 0);
296         }
297 }
298
299 void MAIN::update_bank()
300 {
301         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
302         
303         if((ms & 3) == 0) {
304                 // SD0: INITIALIZE STATE, mz3500sm p.7
305                 SET_BANK(0x0000, 0x0fff, wdmy, ipl + 0x1000);
306                 SET_BANK(0x1000, 0x1fff, wdmy, ipl + 0x1000);
307                 SET_BANK(0x2000, 0x3fff, wdmy, basic + 0x2000);
308                 if(!me1) {
309                         SET_BANK(0x4000, 0x7fff, ram + 0x4000, ram + 0x4000);
310                 }
311                 if(!me2) {
312                         SET_BANK(0x8000, 0xbfff, ram + 0x8000, ram + 0x8000);
313                 }
314                 switch(ma & 0x0f) {
315                 case 0x00: SET_BANK(0xc000, 0xffff, ram + 0x0c000, ram + 0x0c000); break;
316                 case 0x01: SET_BANK(0xc000, 0xffff, ram + 0x00000, ram + 0x00000); break;
317                 case 0x0f: SET_BANK(0xf800, 0xffff, common, common); break;
318                 }
319         } else if((ms & 3) == 1) {
320                 // SD1: SYSTEM LOADING & CP/M, mz3500sm p.9
321                 SET_BANK(0x0000, 0xf7ff, ram, ram);
322                 SET_BANK(0xf800, 0xffff, common, common);
323         } else if((ms & 3) == 2) {
324                 // SD2: ROM based BASIC, mz3500sm p.10
325                 SET_BANK(0x0000, 0x1fff, wdmy, basic);
326                 switch(mo & 0x07) {
327                 case 0x00: SET_BANK(0x2000, 0x3fff, wdmy, basic + 0x2000); break;
328                 case 0x01: SET_BANK(0x2000, 0x3fff, wdmy, basic + 0x4000); break;
329                 case 0x02: SET_BANK(0x2000, 0x3fff, wdmy, basic + 0x6000); break;
330                 case 0x03: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x0000); break;
331                 case 0x04: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x2000); break;
332                 case 0x05: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x4000); break;
333                 case 0x06: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x6000); break;
334                 }
335                 if(!me1) {
336                         SET_BANK(0x4000, 0x7fff, ram + 0x4000, ram + 0x4000);
337                 }
338                 if(!me2) {
339                         SET_BANK(0x8000, 0xbfff, ram + 0x8000, ram + 0x8000);
340                 }
341                 switch(ma & 0x0f) {
342                 case 0x00: SET_BANK(0xc000, 0xffff, ram + 0x0c000, ram + 0x0c000); break;
343                 case 0x01: SET_BANK(0xc000, 0xffff, ram + 0x00000, ram + 0x00000); break;
344                 case 0x02: SET_BANK(0xc000, 0xffff, ram + 0x10000, ram + 0x10000); break;
345                 case 0x03: SET_BANK(0xc000, 0xffff, ram + 0x14000, ram + 0x14000); break;
346                 case 0x04: SET_BANK(0xc000, 0xffff, ram + 0x18000, ram + 0x18000); break;
347                 case 0x05: SET_BANK(0xc000, 0xffff, ram + 0x1c000, ram + 0x1c000); break;
348                 case 0x06: SET_BANK(0xc000, 0xffff, ram + 0x20000, ram + 0x20000); break;
349                 case 0x07: SET_BANK(0xc000, 0xffff, ram + 0x24000, ram + 0x24000); break;
350                 case 0x08: SET_BANK(0xc000, 0xffff, ram + 0x28000, ram + 0x28000); break;
351                 case 0x09: SET_BANK(0xc000, 0xffff, ram + 0x2c000, ram + 0x2c000); break;
352                 case 0x0a: SET_BANK(0xc000, 0xffff, ram + 0x30000, ram + 0x30000); break;
353                 case 0x0b: SET_BANK(0xc000, 0xffff, ram + 0x34000, ram + 0x34000); break;
354                 case 0x0c: SET_BANK(0xc000, 0xffff, ram + 0x38000, ram + 0x38000); break;
355                 case 0x0d: SET_BANK(0xc000, 0xffff, ram + 0x3c000, ram + 0x3c000); break;
356                 case 0x0f: SET_BANK(0xf800, 0xffff, common, common); break;
357                 }
358         } else {
359                 // SD3: RAM based BASIC, mz3500sm p.11
360                 SET_BANK(0x0000, 0x1fff, ram, ram);
361                 switch(mo & 0x07) {
362                 case 0x0: SET_BANK(0x2000, 0x3fff, ram + 0x2000, ram + 0x2000); break;
363                 case 0x1: SET_BANK(0x2000, 0x3fff, ram + 0xc000, ram + 0xc000); break;
364                 case 0x2: SET_BANK(0x2000, 0x3fff, ram + 0xe000, ram + 0xe000); break;
365                 case 0x3: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x0000); break;
366                 case 0x4: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x2000); break;
367                 case 0x5: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x4000); break;
368                 case 0x6: SET_BANK(0x2000, 0x3fff, wdmy, ext + 0x6000); break;
369                 }
370                 if(!me1) {
371                         SET_BANK(0x4000, 0x7fff, ram + 0x4000, ram + 0x4000);
372                 }
373                 if(!me2) {
374                         SET_BANK(0x8000, 0xbfff, ram + 0x8000, ram + 0x8000);
375                 }
376                 switch(ma & 0x0f) {
377                 case 0x00: SET_BANK(0xc000, 0xffff, ram + 0x10000, ram + 0x10000); break;
378                 case 0x01: SET_BANK(0xc000, 0xffff, ram + 0x14000, ram + 0x14000); break;
379                 case 0x02: SET_BANK(0xc000, 0xffff, ram + 0x18000, ram + 0x18000); break;
380                 case 0x03: SET_BANK(0xc000, 0xffff, ram + 0x1c000, ram + 0x1c000); break;
381                 case 0x04: SET_BANK(0xc000, 0xffff, ram + 0x20000, ram + 0x20000); break;
382                 case 0x05: SET_BANK(0xc000, 0xffff, ram + 0x24000, ram + 0x24000); break;
383                 case 0x06: SET_BANK(0xc000, 0xffff, ram + 0x28000, ram + 0x28000); break;
384                 case 0x07: SET_BANK(0xc000, 0xffff, ram + 0x2c000, ram + 0x2c000); break;
385                 case 0x08: SET_BANK(0xc000, 0xffff, ram + 0x30000, ram + 0x30000); break;
386                 case 0x09: SET_BANK(0xc000, 0xffff, ram + 0x34000, ram + 0x34000); break;
387                 case 0x0a: SET_BANK(0xc000, 0xffff, ram + 0x38000, ram + 0x38000); break;
388                 case 0x0b: SET_BANK(0xc000, 0xffff, ram + 0x3c000, ram + 0x3c000); break;
389                 case 0x0f: SET_BANK(0xf800, 0xffff, common, common); break;
390                 }
391         }
392 }
393
394 #define STATE_VERSION   2
395
396 bool MAIN::process_state(FILEIO* state_fio, bool loading)
397 {
398         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
399                 return false;
400         }
401         if(!state_fio->StateCheckInt32(this_device_id)) {
402                 return false;
403         }
404         state_fio->StateBuffer(ram, sizeof(ram), 1);
405         state_fio->StateBuffer(common, sizeof(common), 1);
406         state_fio->StateUint8(ma);
407         state_fio->StateUint8(ms);
408         state_fio->StateUint8(mo);
409         state_fio->StateBool(me1);
410         state_fio->StateBool(me2);
411         state_fio->StateUint8(srqb);
412         state_fio->StateUint8(sres);
413         state_fio->StateBool(sack);
414         state_fio->StateBool(srdy);
415         state_fio->StateBool(intfd);
416         state_fio->StateBool(int0);
417         state_fio->StateBool(int1);
418         state_fio->StateBool(int2);
419         state_fio->StateBool(int3);
420         state_fio->StateBool(int4);
421         state_fio->StateBool(me);
422         state_fio->StateBool(e1);
423         state_fio->StateUint8(inp);
424         state_fio->StateBool(motor);
425         state_fio->StateBool(drq);
426         state_fio->StateBool(index);
427         state_fio->StateBool(crt_400line);
428         
429         // post process
430         if(loading) {
431                  update_bank();
432         }
433         return true;
434 }
435
436 }