OSDN Git Service

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