2 SHARP MZ-80K/C Emulator 'EmuZ-80K'
3 SHARP MZ-1200 Emulator 'EmuZ-1200'
5 Author : Takeda.Toshiya
8 SHARP MZ-80A Emulator 'EmuZ-80A'
21 #define EVENT_HBLANK 2
23 #define SET_BANK(s, e, w, r) { \
24 int sb = (s) >> 10, eb = (e) >> 10; \
25 for(int i = sb; i <= eb; i++) { \
29 wbank[i] = (w) + 0x400 * (i - sb); \
34 rbank[i] = (r) + 0x400 * (i - sb); \
39 void MEMORY::initialize()
42 memset(ram, 0, sizeof(ram));
43 memset(vram, 0, sizeof(vram));
44 memset(ipl, 0xff, sizeof(ipl));
45 #if defined(_MZ1200) || defined(_MZ80A)
46 memset(ext, 0xff, sizeof(ext));
48 #if defined(SUPPORT_MZ80AIF) || defined(SUPPORT_MZ80FIO)
49 memset(fdif, 0xff, sizeof(fdif));
51 memset(rdmy, 0xff, sizeof(rdmy));
54 FILEIO* fio = new FILEIO();
55 if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
56 fio->Fread(ipl, sizeof(ipl), 1);
59 #if defined(_MZ1200) || defined(_MZ80A)
60 if(fio->Fopen(create_local_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
61 fio->Fread(ext, sizeof(ext), 1);
65 #if defined(SUPPORT_MZ80AIF) || defined(SUPPORT_MZ80FIO)
66 if(fio->Fopen(create_local_path(_T("FDIF.ROM")), FILEIO_READ_BINARY)) {
67 fio->Fread(fdif, sizeof(fdif), 1);
71 if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
72 fio->Fread(font, sizeof(font), 1);
80 SET_BANK(0x0000, 0x0fff, wdmy, ipl);
81 SET_BANK(0x1000, 0xbfff, ram + 0x1000, ram + 0x1000);
82 SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
83 #if defined(_MZ1200) || defined(_MZ80A)
84 SET_BANK(0xd000, 0xd7ff, vram, vram); // VRAM 2KB
85 SET_BANK(0xd800, 0xdfff, wdmy, rdmy);
87 SET_BANK(0xd000, 0xd3ff, vram, vram); // VRAM 1KB
88 SET_BANK(0xd400, 0xd7ff, vram, vram);
89 SET_BANK(0xd800, 0xdbff, vram, vram);
90 SET_BANK(0xdc00, 0xdfff, vram, vram);
92 #if defined(_MZ1200) || defined(_MZ80A)
93 SET_BANK(0xe000, 0xe7ff, wdmy, rdmy);
94 SET_BANK(0xe800, 0xefff, wdmy, ext);
96 SET_BANK(0xe000, 0xefff, wdmy, rdmy);
98 #if defined(SUPPORT_MZ80FIO)
99 SET_BANK(0xf000, 0xf3ff, wdmy, fdif);
100 SET_BANK(0xf400, 0xffff, wdmy, rdmy);
102 SET_BANK(0xf000, 0xffff, wdmy, rdmy);
106 // init scroll register
107 e200 = 0x00; // scroll
110 memset(pcg, 0, sizeof(pcg));
111 memcpy(pcg + 0x000, font, 0x400); // copy pattern of 00h-7fh
113 memcpy(pcg + 0x800, font, 0x400);
117 palette_pc[0] = RGB_COLOR(0, 0, 0);
118 #if defined(_MZ1200) || defined(_MZ80A)
119 palette_pc[1] = RGB_COLOR(0, 255, 0);
121 if(config.monitor_type) {
122 palette_pc[1] = RGB_COLOR(0, 255, 0);
124 palette_pc[1] = RGB_COLOR(255, 255, 255);
129 register_vline_event(this);
130 register_event_by_clock(this, EVENT_TEMPO, CPU_CLOCKS / 64, true, NULL); // 32hz * 2
131 register_event_by_clock(this, EVENT_BLINK, CPU_CLOCKS / 3, true, NULL); // 1.5hz * 2
136 #if defined(_MZ1200) || defined(_MZ80A)
139 update_memory_swap();
141 #if defined(SUPPORT_MZ80AIF)
143 fdc_irq = fdc_drq = false;
144 update_fdif_rom_bank();
147 tempo = blink = false;
149 #if defined(_MZ1200) || defined(_MZ80A)
150 hblank = reverse = false;
152 pcg_data = pcg_addr = 0;
155 // motor is always rotating...
156 d_pio->write_signal(SIG_I8255_PORT_C, 0xff, 0x10);
159 void MEMORY::event_vline(int v, int clock)
162 if(0 <= v && v < 200) {
164 int ptr = (v >> 3) * 40 + (int)(e200 << 3); // scroll
166 int ptr = (v >> 3) * 40;
168 bool pcg_active = ((config.dipswitch & 1) && !(pcg_ctrl & 8));
170 uint8_t *pcg_ptr = pcg + ((pcg_ctrl & 4) ? 0x800 : 0);
175 for(int x = 0; x < 320; x += 8) {
176 int code = vram[(ptr++) & 0x7ff] << 3;
177 uint8_t pat = pcg_active ? pcg_ptr[code | (v & 7)] : font[code | (v & 7)];
179 // 8255(PIO) PC0 is /V-GATE 2016.11.21 by Suga
180 if((d_pio->read_io8(2) & 0x01) == 0x00) {
183 #if defined(_MZ1200) || defined(_MZ80A)
188 uint8_t* dest = &screen[v][x];
190 dest[0] = (pat & 0x80) >> 7;
191 dest[1] = (pat & 0x40) >> 6;
192 dest[2] = (pat & 0x20) >> 5;
193 dest[3] = (pat & 0x10) >> 4;
194 dest[4] = (pat & 0x08) >> 3;
195 dest[5] = (pat & 0x04) >> 2;
196 dest[6] = (pat & 0x02) >> 1;
197 dest[7] = (pat & 0x01) >> 0;
203 d_pio->write_signal(SIG_I8255_PORT_C, 0xff, 0x80);
204 } else if(v == 200) {
205 d_pio->write_signal(SIG_I8255_PORT_C, 0, 0x80);
208 #if defined(_MZ1200) || defined(_MZ80A)
211 register_event_by_clock(this, EVENT_HBLANK, 92, false, NULL);
215 void MEMORY::event_callback(int event_id, int err)
217 if(event_id == EVENT_TEMPO) {
220 } else if(event_id == EVENT_BLINK) {
222 d_pio->write_signal(SIG_I8255_PORT_C, (blink = !blink) ? 0xff : 0, 0x40);
223 #if defined(_MZ1200) || defined(_MZ80A)
224 } else if(event_id == EVENT_HBLANK) {
230 void MEMORY::write_data8(uint32_t addr, uint32_t data)
233 if(0xe000 <= addr && addr <= 0xe7ff) {
236 case 0xe000: case 0xe001: case 0xe002: case 0xe003:
237 d_pio->write_io8(addr & 3, data);
239 case 0xe004: case 0xe005: case 0xe006: case 0xe007:
240 d_ctc->write_io8(addr & 3, data);
244 d_ctc->write_signal(SIG_I8253_GATE_0, data, 1);
253 if(!(pcg_ctrl & 0x10) && (data & 0x10)) {
254 int offset = pcg_addr | ((data & 3) << 8);
256 pcg[offset | ((data & 4) ? 0xc00 : 0x400)] = (data & 0x20) ? font[offset | 0x400] : pcg_data;
258 pcg[offset | 0x400 ] = (data & 0x20) ? font[offset | 0x400] : pcg_data;
266 wbank[addr >> 10][addr & 0x3ff] = data;
269 uint32_t MEMORY::read_data8(uint32_t addr)
272 if(0xe000 <= addr && addr <= 0xe7ff) {
275 case 0xe000: case 0xe001: case 0xe002: case 0xe003:
276 return d_pio->read_io8(addr & 3);
277 case 0xe004: case 0xe005: case 0xe006: case 0xe007:
278 return d_ctc->read_io8(addr & 3);
280 #if defined(_MZ1200) || defined(_MZ80A)
281 return (hblank ? 0x80 : 0) | (tempo ? 1 : 0) | 0x7e;
283 return (tempo ? 1 : 0) | 0xfe;
285 #if defined(_MZ1200) || defined(_MZ80A)
290 update_memory_swap();
297 update_memory_swap();
311 if(0xe200 <= addr && addr <= 0xe2ff) {
312 e200 = addr & 0xff; // scroll
319 return rbank[addr >> 10][addr & 0x3ff];
322 #if defined(_MZ1200) || defined(_MZ80A)
323 void MEMORY::update_memory_swap()
326 SET_BANK(0x0000, 0x0fff, ram + 0xc000, ram + 0xc000);
327 SET_BANK(0xc000, 0xcfff, wdmy, ipl);
329 SET_BANK(0x0000, 0x0fff, wdmy, ipl);
330 SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
335 #if defined(SUPPORT_MZ80AIF)
336 void MEMORY::update_fdif_rom_bank()
338 // FD IF ROM BANK switching
340 // F000-F7FF FD IF (MZ-80AIF) ROM offset 0x400
341 SET_BANK(0xf000, 0xf3ff, wdmy, fdif + 0x400 ); // FD IF ROM 1KB (2KB / 2)
342 SET_BANK(0xf400, 0xf7ff, wdmy, fdif + 0x400 ); // FD IF ROM ghost
344 // F000-F7FF FD IF (MZ-80AIF) ROM offset 0
345 SET_BANK(0xf000, 0xf3ff, wdmy, fdif ); // FD IF ROM 1KB (2KB / 2)
346 SET_BANK(0xf400, 0xf7ff, wdmy, fdif ); // FD IF ROM ghost
351 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
353 bool signal = ((data & mask) != 0);
355 if(id == SIG_MEMORY_VGATE) {
357 #if defined(SUPPORT_MZ80AIF)
358 } else if(id == SIG_MEMORY_FDC_IRQ) {
359 if(fdc_irq != signal) {
361 //#ifdef _FDC_DEBUG_LOG
362 if(config.special_debug_fdc) this->out_debug_log(_T("MEM\tfdc_irq=%2x\n"), fdc_irq);
364 // update_fdif_rom_bank();
366 } else if(id == SIG_MEMORY_FDC_DRQ) {
367 if(fdc_drq != signal) {
369 //#ifdef _FDC_DEBUG_LOG
370 if(config.special_debug_fdc) this->out_debug_log(_T("MEM\tfdc_drq=%2x\n"), fdc_drq);
372 update_fdif_rom_bank();
379 void MEMORY::update_config()
381 if(config.monitor_type) {
382 palette_pc[1] = RGB_COLOR(0, 255, 0);
384 palette_pc[1] = RGB_COLOR(255, 255, 255);
389 void MEMORY::draw_screen()
391 // copy to real screen
392 emu->set_vm_screen_lines(200);
395 for(int y = 0; y < 200; y++) {
396 scrntype_t* dest = emu->get_screen_buffer(y);
397 uint8_t* src = screen[y];
399 for(int x = 0; x < 320; x++) {
400 dest[x] = palette_pc[src[x] & 1];
404 for(int y = 0; y < 200; y++) {
405 scrntype_t* dest = emu->get_screen_buffer(y);
406 memset(dest, 0, sizeof(scrntype_t) * 320);
411 #define STATE_VERSION 3
413 #include "../../statesub.h"
415 void MEMORY::decl_state()
417 enter_decl_state(STATE_VERSION);
419 DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
420 DECL_STATE_ENTRY_1D_ARRAY(vram, sizeof(vram));
421 DECL_STATE_ENTRY_BOOL(tempo);
422 DECL_STATE_ENTRY_BOOL(blink);
423 #if defined(_MZ1200) || defined(_MZ80A)
424 DECL_STATE_ENTRY_BOOL(hblank);
425 DECL_STATE_ENTRY_BOOL(memory_swap);
427 #if defined(SUPPORT_MZ80AIF)
428 DECL_STATE_ENTRY_BOOL(fdc_irq);
429 DECL_STATE_ENTRY_BOOL(fdc_drq);
431 DECL_STATE_ENTRY_BOOL(vgate);
432 #if defined(_MZ1200) || defined(_MZ80A)
433 DECL_STATE_ENTRY_BOOL(reverse);
436 DECL_STATE_ENTRY_UINT32(e200);
438 DECL_STATE_ENTRY_1D_ARRAY(&(pcg[0x400]), 0x400);
440 DECL_STATE_ENTRY_1D_ARRAY(&(pcg[0xc00]), 0x400);
442 DECL_STATE_ENTRY_UINT8(pcg_data);
443 DECL_STATE_ENTRY_UINT8(pcg_addr);
444 DECL_STATE_ENTRY_UINT8(pcg_ctrl);
449 void MEMORY::save_state(FILEIO* state_fio)
452 if(state_entry != NULL) {
453 state_entry->save_state(state_fio);
455 // state_fio->FputUint32(STATE_VERSION);
456 // state_fio->FputInt32(this_device_id);
458 // state_fio->Fwrite(ram, sizeof(ram), 1);
459 // state_fio->Fwrite(vram, sizeof(vram), 1);
460 // state_fio->FputBool(tempo);
461 // state_fio->FputBool(blink);
462 //#if defined(_MZ1200) || defined(_MZ80A)
463 // state_fio->FputBool(hblank);
464 // state_fio->FputBool(memory_swap);
466 //#if defined(SUPPORT_MZ80AIF)
467 // state_fio->FputBool(fdc_irq);
468 // state_fio->FputBool(fdc_drq);
470 // vgate = state_fio->FgetBool();
471 //#if defined(_MZ1200) || defined(_MZ80A)
472 // reverse = state_fio->FgetBool();
474 //#if defined(_MZ80A)
475 // state_fio->FputUint32(e200);
477 // state_fio->Fwrite(pcg + 0x400, 0x400, 1);
478 //#if defined(_MZ1200)
479 // state_fio->Fwrite(pcg + 0xc00, 0x400, 1);
481 // state_fio->FputUint8(pcg_data);
482 // state_fio->FputUint8(pcg_addr);
483 // state_fio->FputUint8(pcg_ctrl);
486 bool MEMORY::load_state(FILEIO* state_fio)
489 if(state_entry != NULL) {
490 mb = state_entry->load_state(state_fio);
495 // if(state_fio->FgetUint32() != STATE_VERSION) {
498 // if(state_fio->FgetInt32() != this_device_id) {
501 // state_fio->Fread(ram, sizeof(ram), 1);
502 // state_fio->Fread(vram, sizeof(vram), 1);
503 // tempo = state_fio->FgetBool();
504 // blink = state_fio->FgetBool();
505 //#if defined(_MZ1200) || defined(_MZ80A)
506 // hblank = state_fio->FgetBool();
507 // memory_swap = state_fio->FgetBool();
509 //#if defined(SUPPORT_MZ80AIF)
510 // fdc_irq = state_fio->FgetBool();
511 // fdc_drq = state_fio->FgetBool();
513 // state_fio->FputBool(vgate);
514 //#if defined(_MZ1200) || defined(_MZ80A)
515 // state_fio->FputBool(reverse);
517 //#if defined(_MZ80A)
518 // e200 = state_fio->FgetUint32();
520 // state_fio->Fread(pcg + 0x400, 0x400, 1);
521 //#if defined(_MZ1200)
522 // state_fio->Fread(pcg + 0xc00, 0x400, 1);
524 // pcg_data = state_fio->FgetUint8();
525 // pcg_addr = state_fio->FgetUint8();
526 // pcg_ctrl = state_fio->FgetUint8();
529 #if defined(_MZ1200) || defined(_MZ80A)
530 update_memory_swap();
532 #if defined(SUPPORT_MZ80AIF)
533 update_fdif_rom_bank();
538 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
540 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
543 if(!state_fio->StateCheckInt32(this_device_id)) {
546 state_fio->StateBuffer(ram, sizeof(ram), 1);
547 state_fio->StateBuffer(vram, sizeof(vram), 1);
548 state_fio->StateBool(tempo);
549 state_fio->StateBool(blink);
550 #if defined(_MZ1200) || defined(_MZ80A)
551 state_fio->StateBool(hblank);
552 state_fio->StateBool(memory_swap);
554 #if defined(SUPPORT_MZ80AIF)
555 state_fio->StateBool(fdc_irq);
556 state_fio->StateBool(fdc_drq);
558 state_fio->StateBool(vgate);
559 #if defined(_MZ1200) || defined(_MZ80A)
560 state_fio->StateBool(reverse);
563 state_fio->StateUint32(e200);
565 state_fio->StateBuffer(pcg + 0x400, 0x400, 1);
567 state_fio->StateBuffer(pcg + 0xc00, 0x400, 1);
569 state_fio->StateUint8(pcg_data);
570 state_fio->StateUint8(pcg_addr);
571 state_fio->StateUint8(pcg_ctrl);
575 #if defined(_MZ1200) || defined(_MZ80A)
576 update_memory_swap();
578 #if defined(SUPPORT_MZ80AIF)
579 update_fdif_rom_bank();