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
25 #define SET_BANK(s, e, w, r) { \
26 int sb = (s) >> 10, eb = (e) >> 10; \
27 for(int i = sb; i <= eb; i++) { \
31 wbank[i] = (w) + 0x400 * (i - sb); \
36 rbank[i] = (r) + 0x400 * (i - sb); \
41 void MEMORY::initialize()
44 memset(ram, 0, sizeof(ram));
45 memset(vram, 0, sizeof(vram));
46 memset(ipl, 0xff, sizeof(ipl));
47 #if defined(_MZ1200) || defined(_MZ80A)
48 memset(ext, 0xff, sizeof(ext));
50 #if defined(SUPPORT_MZ80AIF) || defined(SUPPORT_MZ80FIO)
51 memset(fdif, 0xff, sizeof(fdif));
53 memset(rdmy, 0xff, sizeof(rdmy));
56 FILEIO* fio = new FILEIO();
57 if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
58 fio->Fread(ipl, sizeof(ipl), 1);
61 #if defined(_MZ1200) || defined(_MZ80A)
62 if(fio->Fopen(create_local_path(_T("EXT.ROM")), FILEIO_READ_BINARY)) {
63 fio->Fread(ext, sizeof(ext), 1);
67 #if defined(SUPPORT_MZ80AIF) || defined(SUPPORT_MZ80FIO)
68 if(fio->Fopen(create_local_path(_T("FDIF.ROM")), FILEIO_READ_BINARY)) {
69 fio->Fread(fdif, sizeof(fdif), 1);
73 if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
74 fio->Fread(font, sizeof(font), 1);
82 SET_BANK(0x0000, 0x0fff, wdmy, ipl);
83 SET_BANK(0x1000, 0xbfff, ram + 0x1000, ram + 0x1000);
84 SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
85 #if defined(_MZ1200) || defined(_MZ80A)
86 SET_BANK(0xd000, 0xd7ff, vram, vram); // VRAM 2KB
87 SET_BANK(0xd800, 0xdfff, wdmy, rdmy);
89 SET_BANK(0xd000, 0xd3ff, vram, vram); // VRAM 1KB
90 SET_BANK(0xd400, 0xd7ff, vram, vram);
91 SET_BANK(0xd800, 0xdbff, vram, vram);
92 SET_BANK(0xdc00, 0xdfff, vram, vram);
94 #if defined(_MZ1200) || defined(_MZ80A)
95 SET_BANK(0xe000, 0xe7ff, wdmy, rdmy);
96 SET_BANK(0xe800, 0xefff, wdmy, ext);
98 SET_BANK(0xe000, 0xefff, wdmy, rdmy);
100 #if defined(SUPPORT_MZ80FIO)
101 SET_BANK(0xf000, 0xf3ff, wdmy, fdif);
102 SET_BANK(0xf400, 0xffff, wdmy, rdmy);
104 SET_BANK(0xf000, 0xffff, wdmy, rdmy);
108 // init scroll register
109 e200 = 0x00; // scroll
112 memset(pcg, 0, sizeof(pcg));
113 memcpy(pcg + 0x000, font, 0x400); // copy pattern of 00h-7fh
115 memcpy(pcg + 0x800, font, 0x400);
119 palette_pc[0] = RGB_COLOR(0, 0, 0);
120 #if defined(_MZ1200) || defined(_MZ80A)
121 palette_pc[1] = RGB_COLOR(0, 255, 0);
123 if(config.monitor_type) {
124 palette_pc[1] = RGB_COLOR(0, 255, 0);
126 palette_pc[1] = RGB_COLOR(255, 255, 255);
131 register_vline_event(this);
132 register_event_by_clock(this, EVENT_TEMPO, CPU_CLOCKS / 64, true, NULL); // 32hz * 2
133 register_event_by_clock(this, EVENT_BLINK, CPU_CLOCKS / 3, true, NULL); // 1.5hz * 2
138 #if defined(_MZ1200) || defined(_MZ80A)
141 update_memory_swap();
143 #if defined(SUPPORT_MZ80AIF)
145 fdc_irq = fdc_drq = false;
146 update_fdif_rom_bank();
149 tempo = blink = false;
151 #if defined(_MZ1200) || defined(_MZ80A)
152 hblank = reverse = false;
154 pcg_data = pcg_addr = 0;
157 // motor is always rotating...
158 d_pio->write_signal(SIG_I8255_PORT_C, 0xff, 0x10);
161 void MEMORY::event_vline(int v, int clock)
164 if(0 <= v && v < 200) {
166 int ptr = (v >> 3) * 40 + (int)(e200 << 3); // scroll
168 int ptr = (v >> 3) * 40;
170 bool pcg_active = ((config.dipswitch & 1) && !(pcg_ctrl & 8));
172 uint8_t *pcg_ptr = pcg + ((pcg_ctrl & 4) ? 0x800 : 0);
177 for(int x = 0; x < 320; x += 8) {
178 int code = vram[(ptr++) & 0x7ff] << 3;
179 uint8_t pat = pcg_active ? pcg_ptr[code | (v & 7)] : font[code | (v & 7)];
181 // 8255(PIO) PC0 is /V-GATE 2016.11.21 by Suga
182 if((d_pio->read_io8(2) & 0x01) == 0x00) {
185 #if defined(_MZ1200) || defined(_MZ80A)
190 uint8_t* dest = &screen[v][x];
192 dest[0] = (pat & 0x80) >> 7;
193 dest[1] = (pat & 0x40) >> 6;
194 dest[2] = (pat & 0x20) >> 5;
195 dest[3] = (pat & 0x10) >> 4;
196 dest[4] = (pat & 0x08) >> 3;
197 dest[5] = (pat & 0x04) >> 2;
198 dest[6] = (pat & 0x02) >> 1;
199 dest[7] = (pat & 0x01) >> 0;
205 d_pio->write_signal(SIG_I8255_PORT_C, 0xff, 0x80);
206 } else if(v == 200) {
207 d_pio->write_signal(SIG_I8255_PORT_C, 0, 0x80);
210 #if defined(_MZ1200) || defined(_MZ80A)
213 register_event_by_clock(this, EVENT_HBLANK, 92, false, NULL);
217 void MEMORY::event_callback(int event_id, int err)
219 if(event_id == EVENT_TEMPO) {
222 } else if(event_id == EVENT_BLINK) {
224 d_pio->write_signal(SIG_I8255_PORT_C, (blink = !blink) ? 0xff : 0, 0x40);
225 #if defined(_MZ1200) || defined(_MZ80A)
226 } else if(event_id == EVENT_HBLANK) {
232 void MEMORY::write_data8(uint32_t addr, uint32_t data)
235 if(0xe000 <= addr && addr <= 0xe7ff) {
238 case 0xe000: case 0xe001: case 0xe002: case 0xe003:
239 d_pio->write_io8(addr & 3, data);
241 case 0xe004: case 0xe005: case 0xe006: case 0xe007:
242 d_ctc->write_io8(addr & 3, data);
246 d_ctc->write_signal(SIG_I8253_GATE_0, data, 1);
255 if(!(pcg_ctrl & 0x10) && (data & 0x10)) {
256 int offset = pcg_addr | ((data & 3) << 8);
258 pcg[offset | ((data & 4) ? 0xc00 : 0x400)] = (data & 0x20) ? font[offset | 0x400] : pcg_data;
260 pcg[offset | 0x400 ] = (data & 0x20) ? font[offset | 0x400] : pcg_data;
268 wbank[addr >> 10][addr & 0x3ff] = data;
271 uint32_t MEMORY::read_data8(uint32_t addr)
274 if(0xe000 <= addr && addr <= 0xe7ff) {
277 case 0xe000: case 0xe001: case 0xe002: case 0xe003:
278 return d_pio->read_io8(addr & 3);
279 case 0xe004: case 0xe005: case 0xe006: case 0xe007:
280 return d_ctc->read_io8(addr & 3);
282 #if defined(_MZ1200) || defined(_MZ80A)
283 return (hblank ? 0x80 : 0) | (tempo ? 1 : 0) | 0x7e;
285 return (tempo ? 1 : 0) | 0xfe;
287 #if defined(_MZ1200) || defined(_MZ80A)
292 update_memory_swap();
299 update_memory_swap();
313 if(0xe200 <= addr && addr <= 0xe2ff) {
314 e200 = addr & 0xff; // scroll
321 return rbank[addr >> 10][addr & 0x3ff];
324 #if defined(_MZ1200) || defined(_MZ80A)
325 void MEMORY::update_memory_swap()
328 SET_BANK(0x0000, 0x0fff, ram + 0xc000, ram + 0xc000);
329 SET_BANK(0xc000, 0xcfff, wdmy, ipl);
331 SET_BANK(0x0000, 0x0fff, wdmy, ipl);
332 SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
337 #if defined(SUPPORT_MZ80AIF)
338 void MEMORY::update_fdif_rom_bank()
340 // FD IF ROM BANK switching
342 // F000-F7FF FD IF (MZ-80AIF) ROM offset 0x400
343 SET_BANK(0xf000, 0xf3ff, wdmy, fdif + 0x400 ); // FD IF ROM 1KB (2KB / 2)
344 SET_BANK(0xf400, 0xf7ff, wdmy, fdif + 0x400 ); // FD IF ROM ghost
346 // F000-F7FF FD IF (MZ-80AIF) ROM offset 0
347 SET_BANK(0xf000, 0xf3ff, wdmy, fdif ); // FD IF ROM 1KB (2KB / 2)
348 SET_BANK(0xf400, 0xf7ff, wdmy, fdif ); // FD IF ROM ghost
353 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
355 bool signal = ((data & mask) != 0);
357 if(id == SIG_MEMORY_VGATE) {
359 #if defined(SUPPORT_MZ80AIF)
360 } else if(id == SIG_MEMORY_FDC_IRQ) {
361 if(fdc_irq != signal) {
363 //#ifdef _FDC_DEBUG_LOG
364 if(config.special_debug_fdc) this->out_debug_log(_T("MEM\tfdc_irq=%2x\n"), fdc_irq);
366 // update_fdif_rom_bank();
368 } else if(id == SIG_MEMORY_FDC_DRQ) {
369 if(fdc_drq != signal) {
371 //#ifdef _FDC_DEBUG_LOG
372 if(config.special_debug_fdc) this->out_debug_log(_T("MEM\tfdc_drq=%2x\n"), fdc_drq);
374 update_fdif_rom_bank();
381 void MEMORY::update_config()
383 if(config.monitor_type) {
384 palette_pc[1] = RGB_COLOR(0, 255, 0);
386 palette_pc[1] = RGB_COLOR(255, 255, 255);
391 void MEMORY::draw_screen()
393 // copy to real screen
394 emu->set_vm_screen_lines(200);
397 for(int y = 0; y < 200; y++) {
398 scrntype_t* dest = emu->get_screen_buffer(y);
399 uint8_t* src = screen[y];
401 for(int x = 0; x < 320; x++) {
402 dest[x] = palette_pc[src[x] & 1];
406 for(int y = 0; y < 200; y++) {
407 scrntype_t* dest = emu->get_screen_buffer(y);
408 memset(dest, 0, sizeof(scrntype_t) * 320);
413 #define STATE_VERSION 3
415 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
417 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
420 if(!state_fio->StateCheckInt32(this_device_id)) {
423 state_fio->StateArray(ram, sizeof(ram), 1);
424 state_fio->StateArray(vram, sizeof(vram), 1);
425 state_fio->StateValue(tempo);
426 state_fio->StateValue(blink);
427 #if defined(_MZ1200) || defined(_MZ80A)
428 state_fio->StateValue(hblank);
429 state_fio->StateValue(memory_swap);
431 #if defined(SUPPORT_MZ80AIF)
432 state_fio->StateValue(fdc_irq);
433 state_fio->StateValue(fdc_drq);
435 state_fio->StateValue(vgate);
436 #if defined(_MZ1200) || defined(_MZ80A)
437 state_fio->StateValue(reverse);
440 state_fio->StateValue(e200);
442 state_fio->StateArray(pcg + 0x400, 0x400, 1);
444 state_fio->StateArray(pcg + 0xc00, 0x400, 1);
446 state_fio->StateValue(pcg_data);
447 state_fio->StateValue(pcg_addr);
448 state_fio->StateValue(pcg_ctrl);
452 #if defined(_MZ1200) || defined(_MZ80A)
453 update_memory_swap();
455 #if defined(SUPPORT_MZ80AIF)
456 update_fdif_rom_bank();