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 MZ80A_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
134 void MZ80A_MEMORY::reset()
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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 MZ80A_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 bool MZ80A_MEMORY::process_state(FILEIO* state_fio, bool loading)
415 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
418 if(!state_fio->StateCheckInt32(this_device_id)) {
421 state_fio->StateBuffer(ram, sizeof(ram), 1);
422 state_fio->StateBuffer(vram, sizeof(vram), 1);
423 state_fio->StateBool(tempo);
424 state_fio->StateBool(blink);
425 #if defined(_MZ1200) || defined(_MZ80A)
426 state_fio->StateBool(hblank);
427 state_fio->StateBool(memory_swap);
429 #if defined(SUPPORT_MZ80AIF)
430 state_fio->StateBool(fdc_irq);
431 state_fio->StateBool(fdc_drq);
433 state_fio->StateBool(vgate);
434 #if defined(_MZ1200) || defined(_MZ80A)
435 state_fio->StateBool(reverse);
438 state_fio->StateUint32(e200);
440 state_fio->StateBuffer(pcg + 0x400, 0x400, 1);
442 state_fio->StateBuffer(pcg + 0xc00, 0x400, 1);
444 state_fio->StateUint8(pcg_data);
445 state_fio->StateUint8(pcg_addr);
446 state_fio->StateUint8(pcg_ctrl);
450 #if defined(_MZ1200) || defined(_MZ80A)
451 update_memory_swap();
453 #if defined(SUPPORT_MZ80AIF)
454 update_fdif_rom_bank();