-/*\r
- SHARP MZ-80B Emulator 'EmuZ-80B'\r
- SHARP MZ-2200 Emulator 'EmuZ-2200'\r
-\r
- Author : Takeda.Toshiya\r
- Date : 2013.03.14-\r
-\r
- [ memory/crtc ]\r
-*/\r
-\r
-#include "memory80b.h"\r
-#include "../i8255.h"\r
-#include "../z80.h"\r
-#include "../../fileio.h"\r
-\r
-#define EVENT_HBLANK 0\r
-\r
-#define MONITOR_TYPE_COLOR 0\r
-#define MONITOR_TYPE_GREEN 1\r
-\r
-#define SET_BANK(s, e, w, r, v) { \\r
- int sb = (s) >> 11, eb = (e) >> 11; \\r
- for(int i = sb; i <= eb; i++) { \\r
- if((w) == wdmy) { \\r
- wbank[i] = wdmy; \\r
- } else { \\r
- wbank[i] = (w) + 0x800 * (i - sb); \\r
- } \\r
- if((r) == rdmy) { \\r
- rbank[i] = rdmy; \\r
- } else { \\r
- rbank[i] = (r) + 0x800 * (i - sb); \\r
- } \\r
- is_vram[i] = v; \\r
- } \\r
-}\r
-\r
-void MEMORY::initialize()\r
-{\r
- // memory\r
- memset(rdmy, 0xff, sizeof(rdmy));\r
- memset(ram, 0, sizeof(ram));\r
- memset(vram, 0, sizeof(vram));\r
- memset(tvram, 0, sizeof(tvram));\r
- memset(ipl, 0xff, sizeof(ipl));\r
- \r
- FILEIO* fio = new FILEIO();\r
- if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {\r
- fio->Fread(ipl, sizeof(ipl), 1);\r
- fio->Fclose();\r
- }\r
- if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {\r
- fio->Fread(font, sizeof(font), 1);\r
- fio->Fclose();\r
- }\r
- delete fio;\r
- \r
- vram_sel = vram_page = 0;\r
- \r
- // crtc\r
- back_color = 0;\r
- text_color = vram_mask = 7;\r
- width80 = reverse = false;\r
- \r
- update_palette();\r
- register_vline_event(this);\r
-}\r
-\r
-void MEMORY::reset()\r
-{\r
- // ipl reset\r
- SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);\r
- SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);\r
- SET_BANK(0x8000, 0xffff, ram, ram, false);\r
- \r
- ipl_selected = true;\r
- update_vram_map();\r
-}\r
-\r
-void MEMORY::special_reset()\r
-{\r
- // reset\r
- SET_BANK(0x0000, 0xffff, ram, ram, false);\r
- \r
- ipl_selected = false;\r
- update_vram_map();\r
-}\r
-\r
-void MEMORY::write_data8(uint32 addr, uint32 data)\r
-{\r
- addr &= 0xffff;\r
- if(!hblank && is_vram[addr >> 11]) {\r
- d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);\r
- }\r
- wbank[addr >> 11][addr & 0x7ff] = data;\r
-}\r
-\r
-uint32 MEMORY::read_data8(uint32 addr)\r
-{\r
- addr &= 0xffff;\r
- if(!hblank && is_vram[addr >> 11]) {\r
- d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);\r
- }\r
- return rbank[addr >> 11][addr & 0x7ff];\r
-}\r
-\r
-uint32 MEMORY::fetch_op(uint32 addr, int *wait)\r
-{\r
- addr &= 0xffff;\r
- *wait = (ipl_selected && addr < 0x800);\r
- return rbank[addr >> 11][addr & 0x7ff];\r
-}\r
-\r
-void MEMORY::write_io8(uint32 addr, uint32 data)\r
-{\r
- switch(addr & 0xff) {\r
-#ifndef _MZ80B\r
- case 0xf4:\r
- back_color = data & 7;\r
- break;\r
- case 0xf5:\r
- text_color = data;\r
- break;\r
- case 0xf6:\r
- vram_mask = data;\r
- break;\r
- case 0xf7:\r
- if(vram_page != (data & 3)) {\r
- vram_page = data & 3;\r
- if(vram_sel == 0x80) {\r
- update_vram_map();\r
- }\r
- }\r
- break;\r
-#else\r
- case 0xf4:\r
- case 0xf5:\r
- case 0xf6:\r
- case 0xf7:\r
- if(vram_page != (data & 7)) {\r
- uint8 prev_page = vram_page;\r
- vram_page = data & 7;\r
- if((prev_page & 1) != (vram_page & 1) && (vram_sel == 0x80 || vram_sel == 0xc0)) {\r
- update_vram_map();\r
- }\r
- }\r
- break;\r
-#endif\r
- }\r
-}\r
-\r
-void MEMORY::write_signal(int id, uint32 data, uint32 mask)\r
-{\r
- if(id == SIG_MEMORY_VRAM_SEL) {\r
- if(vram_sel != (data & mask)) {\r
- vram_sel = data & mask;\r
- update_vram_map();\r
- }\r
- } else if(id == SIG_CRTC_WIDTH80) {\r
- width80 = ((data & mask) != 0);\r
- } else if(id == SIG_CRTC_REVERSE) {\r
- reverse = ((data & mask) == 0);\r
-#ifndef _MZ80B\r
- if(config.monitor_type != MONITOR_TYPE_COLOR)\r
-#endif\r
- update_palette();\r
- }\r
-}\r
-\r
-void MEMORY::event_vline(int v, int clock)\r
-{\r
- if(v == 0) {\r
- d_pio->write_signal(SIG_I8255_PORT_B, 1, 1);\r
- } else if(v == 200) {\r
- d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);\r
- }\r
-// if(v < 200) {\r
- hblank = false;\r
- register_event_by_clock(this, EVENT_HBLANK, 184, false, NULL);\r
-// }\r
-}\r
-\r
-void MEMORY::event_callback(int event_id, int err)\r
-{\r
- if(event_id == EVENT_HBLANK) {\r
- hblank = true;\r
- d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);\r
- }\r
-}\r
-\r
-#ifndef _MZ80B\r
-void MEMORY::update_config()\r
-{\r
- update_palette();\r
-}\r
-#endif\r
-\r
-void MEMORY::update_palette()\r
-{\r
-#ifndef _MZ80B\r
- if(config.monitor_type == MONITOR_TYPE_COLOR) {\r
- for(int i = 0; i < 8; i++) {\r
- palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);\r
- }\r
- } else\r
-#endif\r
- if(reverse) {\r
- for(int i = 0; i < 8; i++) {\r
- palette_pc[i] = RGB_COLOR(0, i ? 0 : 255, 0);\r
- }\r
- } else {\r
- for(int i = 0; i < 8; i++) {\r
- palette_pc[i] = RGB_COLOR(0, i ? 255 : 0, 0);\r
- }\r
- }\r
-}\r
-\r
-void MEMORY::update_vram_map()\r
-{\r
-#ifndef _MZ80B\r
- if(vram_sel == 0x80) {\r
- if(vram_page) {\r
- SET_BANK(0xc000, 0xffff, vram + 0x4000 * vram_page, vram + 0x4000 * vram_page, true);\r
- } else {\r
- SET_BANK(0xc000, 0xffff, wdmy, rdmy, false);\r
- }\r
- } else {\r
- if(ipl_selected) {\r
- SET_BANK(0xc000, 0xffff, ram + 0x4000, ram + 0x4000, false);\r
- } else {\r
- SET_BANK(0xc000, 0xffff, ram + 0xc000, ram + 0xc000, false);\r
- }\r
- if(vram_sel == 0xc0) {\r
- SET_BANK(0xd000, 0xdfff, tvram, tvram, true);\r
- }\r
- }\r
-#else\r
- if(ipl_selected) {\r
- SET_BANK(0x5000, 0x7fff, wdmy, rdmy, false);\r
- SET_BANK(0xd000, 0xffff, ram + 0x5000, ram + 0x5000, false);\r
- } else {\r
- SET_BANK(0x5000, 0x7fff, ram + 0x5000, ram + 0x5000, false);\r
- SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000, false);\r
- }\r
- if(vram_sel == 0x80) {\r
- SET_BANK(0xd000, 0xdfff, tvram, tvram, true);\r
- SET_BANK(0xe000, 0xffff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);\r
- } else if(vram_sel == 0xc0) {\r
- SET_BANK(0x5000, 0x5fff, tvram, tvram, true);\r
- SET_BANK(0x6000, 0x7fff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);\r
- }\r
-#endif\r
-}\r
-\r
-void MEMORY::load_dat_image(_TCHAR* file_path)\r
-{\r
- FILEIO* fio = new FILEIO();\r
- if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {\r
- memset(ram, 0, sizeof(ram));\r
- memset(vram, 0, sizeof(vram));\r
- memset(tvram, 0, sizeof(tvram));\r
- \r
- fio->Fread(ram, sizeof(ram), 1);\r
- fio->Fclose();\r
- vm->special_reset();\r
- }\r
- delete fio;\r
-}\r
-\r
-bool MEMORY::load_mzt_image(_TCHAR* file_path)\r
-{\r
- bool result = false;\r
- bool is_mtw = check_file_extension(file_path, _T(".mtw"));\r
- \r
- if(is_mtw || ipl_selected) {\r
- FILEIO* fio = new FILEIO();\r
- if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {\r
- uint8 header[128];\r
- fio->Fread(header, sizeof(header), 1);\r
- uint16 size = header[0x12] | (header[0x13] << 8);\r
- uint16 offs = header[0x14] | (header[0x15] << 8);\r
- \r
-// if(header[0] == 0x01 && (is_mtw || size > 0x7e00)) {\r
- if(header[0] == 0x01 && offs == 0) {\r
- memset(ram, 0, sizeof(ram));\r
- memset(vram, 0, sizeof(vram));\r
- memset(tvram, 0, sizeof(tvram));\r
- \r
- fio->Fread(ram, size, 1);\r
- vm->special_reset();\r
- result = true;\r
- }\r
- fio->Fclose();\r
- }\r
- delete fio;\r
- }\r
- return result;\r
-}\r
-\r
-void MEMORY::draw_screen()\r
-{\r
- // render text\r
-#ifndef _MZ80B\r
- uint8 color = (text_color & 7) ? (text_color & 7) : 8;\r
-#else\r
- #define color 1\r
-#endif\r
- for(int y = 0, addr = 0; y < 200; y += 8) {\r
- for(int x = 0; x < (width80 ? 80 : 40); x++) {\r
- uint8 code = tvram[addr++];\r
- for(int l = 0; l < 8; l++) {\r
- uint8 pat = font[(code << 3) + l];\r
- uint8* d = &screen_txt[y + l][x << 3];\r
- \r
- d[0] = (pat & 0x80) ? color : 0;\r
- d[1] = (pat & 0x40) ? color : 0;\r
- d[2] = (pat & 0x20) ? color : 0;\r
- d[3] = (pat & 0x10) ? color : 0;\r
- d[4] = (pat & 0x08) ? color : 0;\r
- d[5] = (pat & 0x04) ? color : 0;\r
- d[6] = (pat & 0x02) ? color : 0;\r
- d[7] = (pat & 0x01) ? color : 0;\r
- }\r
- }\r
- }\r
- \r
- // render graphics\r
-#ifndef _MZ80B\r
- if(config.monitor_type != MONITOR_TYPE_COLOR && (vram_mask & 8)) {\r
- memset(screen_gra, 0, sizeof(screen_gra));\r
- } else {\r
- // vram[0x0000-0x3fff] should be always blank\r
- uint8 *vram_b = vram + ((vram_mask & 1) ? 0x4000 : 0);\r
- uint8 *vram_r = vram + ((vram_mask & 2) ? 0x8000 : 0);\r
- uint8 *vram_g = vram + ((vram_mask & 4) ? 0xc000 : 0);\r
- for(int y = 0, addr = 0; y < 200; y++) {\r
- for(int x = 0; x < 80; x++) {\r
- uint8 b = vram_b[addr];\r
- uint8 r = vram_r[addr];\r
- uint8 g = vram_g[addr];\r
- addr++;\r
- uint8* d = &screen_gra[y][x << 3];\r
- \r
- d[0] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);\r
- d[1] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);\r
- d[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);\r
- d[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);\r
- d[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);\r
- d[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);\r
- d[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);\r
- d[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);\r
- }\r
- }\r
- }\r
-#else\r
- if(!(vram_page & 6)) {\r
- memset(screen_gra, 0, sizeof(screen_gra));\r
- } else {\r
- // vram[0x8000-0xbfff] should be always blank\r
- uint8 *vram_1 = vram + ((vram_page & 2) ? 0x0000 : 0x8000);\r
- uint8 *vram_2 = vram + ((vram_page & 4) ? 0x4000 : 0x8000);\r
- for(int y = 0, addr = 0; y < 200; y++) {\r
- for(int x = 0; x < 40; x++) {\r
- uint8 pat = vram_1[addr] | vram_2[addr];\r
- addr++;\r
- uint8* d = &screen_gra[y][x << 3];\r
- \r
- d[0] = (pat & 0x01) >> 0;\r
- d[1] = (pat & 0x02) >> 1;\r
- d[2] = (pat & 0x04) >> 2;\r
- d[3] = (pat & 0x08) >> 3;\r
- d[4] = (pat & 0x10) >> 4;\r
- d[5] = (pat & 0x20) >> 5;\r
- d[6] = (pat & 0x40) >> 6;\r
- d[7] = (pat & 0x80) >> 7;\r
- }\r
- }\r
- }\r
-#endif\r
- \r
- // copy to real screen\r
- for(int y = 0; y < 200; y++) {\r
- scrntype* dest0 = emu->screen_buffer(y * 2 + 0);\r
- scrntype* dest1 = emu->screen_buffer(y * 2 + 1);\r
- uint8* src_txt = screen_txt[y];\r
- uint8* src_gra = screen_gra[y];\r
-#ifndef _MZ80B\r
- uint8 back = (config.monitor_type == MONITOR_TYPE_COLOR) ? back_color : 0;\r
- \r
- if(text_color & 8) {\r
- // graphics > text\r
- for(int x = 0; x < 640; x++) {\r
- uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];\r
- dest0[x] = palette_pc[gra ? gra : txt ? (txt & 7) : back];\r
- }\r
- } else {\r
- // text > graphics\r
- for(int x = 0; x < 640; x++) {\r
- uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];\r
- dest0[x] = palette_pc[txt ? (txt & 7) : gra ? gra : back];\r
- }\r
- }\r
-#else\r
- if(width80) {\r
- for(int x = 0; x < 640; x++) {\r
- uint8 txt = src_txt[x], gra = src_gra[x >> 1];\r
- dest0[x] = palette_pc[txt | gra];\r
- }\r
- } else {\r
- for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {\r
- uint8 txt = src_txt[x], gra = src_gra[x];\r
- dest0[x2] = dest0[x2 + 1] = palette_pc[txt | gra];\r
- }\r
- }\r
-#endif\r
- if(config.scan_line) {\r
- memset(dest1, 0, 640 * sizeof(scrntype));\r
- } else {\r
- memcpy(dest1, dest0, 640 * sizeof(scrntype));\r
- }\r
- }\r
-#ifndef _MZ80B\r
- emu->screen_skip_line = true;\r
-#endif\r
-}\r
-\r
-#define STATE_VERSION 1\r
-\r
-void MEMORY::save_state(FILEIO* state_fio)\r
-{\r
- state_fio->FputUint32(STATE_VERSION);\r
- state_fio->FputInt32(this_device_id);\r
- \r
- state_fio->Fwrite(ram, sizeof(ram), 1);\r
- state_fio->Fwrite(vram, sizeof(vram), 1);\r
- state_fio->Fwrite(tvram, sizeof(tvram), 1);\r
- state_fio->FputBool(ipl_selected);\r
- state_fio->FputUint8(vram_sel);\r
- state_fio->FputUint8(vram_page);\r
- state_fio->FputUint8(back_color);\r
- state_fio->FputUint8(text_color);\r
- state_fio->FputUint8(vram_mask);\r
- state_fio->FputBool(width80);\r
- state_fio->FputBool(reverse);\r
- state_fio->FputBool(hblank);\r
-}\r
-\r
-bool MEMORY::load_state(FILEIO* state_fio)\r
-{\r
- if(state_fio->FgetUint32() != STATE_VERSION) {\r
- return false;\r
- }\r
- if(state_fio->FgetInt32() != this_device_id) {\r
- return false;\r
- }\r
- state_fio->Fread(ram, sizeof(ram), 1);\r
- state_fio->Fread(vram, sizeof(vram), 1);\r
- state_fio->Fread(tvram, sizeof(tvram), 1);\r
- ipl_selected = state_fio->FgetBool();\r
- vram_sel = state_fio->FgetUint8();\r
- vram_page = state_fio->FgetUint8();\r
- back_color = state_fio->FgetUint8();\r
- text_color = state_fio->FgetUint8();\r
- vram_mask = state_fio->FgetUint8();\r
- width80 = state_fio->FgetBool();\r
- reverse = state_fio->FgetBool();\r
- hblank = state_fio->FgetBool();\r
- \r
- // post process\r
- if(ipl_selected) {\r
- SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);\r
- SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);\r
- SET_BANK(0x8000, 0xffff, ram, ram, false);\r
- } else {\r
- SET_BANK(0x0000, 0xffff, ram, ram, false);\r
- }\r
- update_vram_map();\r
- update_palette();\r
- return true;\r
-}\r
-\r
+/*
+ SHARP MZ-80B Emulator 'EmuZ-80B'
+ SHARP MZ-2200 Emulator 'EmuZ-2200'
+
+ Author : Takeda.Toshiya
+ Date : 2013.03.14-
+
+ [ memory/crtc ]
+*/
+
+#include "memory80b.h"
+#include "../i8255.h"
+#include "../z80.h"
+#include "../../fileio.h"
+
+#define EVENT_HBLANK 0
+
+#define MONITOR_TYPE_COLOR 0
+#define MONITOR_TYPE_GREEN 1
+
+#define SET_BANK(s, e, w, r, v) { \
+ int sb = (s) >> 11, eb = (e) >> 11; \
+ for(int i = sb; i <= eb; i++) { \
+ if((w) == wdmy) { \
+ wbank[i] = wdmy; \
+ } else { \
+ wbank[i] = (w) + 0x800 * (i - sb); \
+ } \
+ if((r) == rdmy) { \
+ rbank[i] = rdmy; \
+ } else { \
+ rbank[i] = (r) + 0x800 * (i - sb); \
+ } \
+ is_vram[i] = v; \
+ } \
+}
+
+void MEMORY::initialize()
+{
+ // memory
+ memset(rdmy, 0xff, sizeof(rdmy));
+ memset(ram, 0, sizeof(ram));
+ memset(vram, 0, sizeof(vram));
+ memset(tvram, 0, sizeof(tvram));
+ memset(ipl, 0xff, sizeof(ipl));
+
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
+ fio->Fread(ipl, sizeof(ipl), 1);
+ fio->Fclose();
+ }
+ if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
+ fio->Fread(font, sizeof(font), 1);
+ fio->Fclose();
+ }
+ delete fio;
+
+ vram_sel = vram_page = 0;
+
+ // crtc
+ back_color = 0;
+ text_color = vram_mask = 7;
+ width80 = reverse = false;
+
+ update_palette();
+ register_vline_event(this);
+}
+
+void MEMORY::reset()
+{
+ // ipl reset
+ SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);
+ SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);
+ SET_BANK(0x8000, 0xffff, ram, ram, false);
+
+ ipl_selected = true;
+ update_vram_map();
+}
+
+void MEMORY::special_reset()
+{
+ // reset
+ SET_BANK(0x0000, 0xffff, ram, ram, false);
+
+ ipl_selected = false;
+ update_vram_map();
+}
+
+void MEMORY::write_data8(uint32 addr, uint32 data)
+{
+ addr &= 0xffff;
+ if(!hblank && is_vram[addr >> 11]) {
+ d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
+ }
+ wbank[addr >> 11][addr & 0x7ff] = data;
+}
+
+uint32 MEMORY::read_data8(uint32 addr)
+{
+ addr &= 0xffff;
+ if(!hblank && is_vram[addr >> 11]) {
+ d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
+ }
+ return rbank[addr >> 11][addr & 0x7ff];
+}
+
+uint32 MEMORY::fetch_op(uint32 addr, int *wait)
+{
+ addr &= 0xffff;
+ *wait = (ipl_selected && addr < 0x800);
+ return rbank[addr >> 11][addr & 0x7ff];
+}
+
+void MEMORY::write_io8(uint32 addr, uint32 data)
+{
+ switch(addr & 0xff) {
+#ifndef _MZ80B
+ case 0xf4:
+ back_color = data & 7;
+ break;
+ case 0xf5:
+ text_color = data;
+ break;
+ case 0xf6:
+ vram_mask = data;
+ break;
+ case 0xf7:
+ if(vram_page != (data & 3)) {
+ vram_page = data & 3;
+ if(vram_sel == 0x80) {
+ update_vram_map();
+ }
+ }
+ break;
+#else
+ case 0xf4:
+ case 0xf5:
+ case 0xf6:
+ case 0xf7:
+ if(vram_page != (data & 7)) {
+ uint8 prev_page = vram_page;
+ vram_page = data & 7;
+ if((prev_page & 1) != (vram_page & 1) && (vram_sel == 0x80 || vram_sel == 0xc0)) {
+ update_vram_map();
+ }
+ }
+ break;
+#endif
+ }
+}
+
+void MEMORY::write_signal(int id, uint32 data, uint32 mask)
+{
+ if(id == SIG_MEMORY_VRAM_SEL) {
+ if(vram_sel != (data & mask)) {
+ vram_sel = data & mask;
+ update_vram_map();
+ }
+ } else if(id == SIG_CRTC_WIDTH80) {
+ width80 = ((data & mask) != 0);
+ } else if(id == SIG_CRTC_REVERSE) {
+ reverse = ((data & mask) == 0);
+#ifndef _MZ80B
+ if(config.monitor_type != MONITOR_TYPE_COLOR)
+#endif
+ update_palette();
+ }
+}
+
+void MEMORY::event_vline(int v, int clock)
+{
+ if(v == 0) {
+ d_pio->write_signal(SIG_I8255_PORT_B, 1, 1);
+ } else if(v == 200) {
+ d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);
+ }
+// if(v < 200) {
+ hblank = false;
+ register_event_by_clock(this, EVENT_HBLANK, 184, false, NULL);
+// }
+}
+
+void MEMORY::event_callback(int event_id, int err)
+{
+ if(event_id == EVENT_HBLANK) {
+ hblank = true;
+ d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
+ }
+}
+
+#ifndef _MZ80B
+void MEMORY::update_config()
+{
+ update_palette();
+}
+#endif
+
+void MEMORY::update_palette()
+{
+#ifndef _MZ80B
+ if(config.monitor_type == MONITOR_TYPE_COLOR) {
+ for(int i = 0; i < 8; i++) {
+ palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
+ }
+ } else
+#endif
+ if(reverse) {
+ for(int i = 0; i < 8; i++) {
+ palette_pc[i] = RGB_COLOR(0, i ? 0 : 255, 0);
+ }
+ } else {
+ for(int i = 0; i < 8; i++) {
+ palette_pc[i] = RGB_COLOR(0, i ? 255 : 0, 0);
+ }
+ }
+}
+
+void MEMORY::update_vram_map()
+{
+#ifndef _MZ80B
+ if(vram_sel == 0x80) {
+ if(vram_page) {
+ SET_BANK(0xc000, 0xffff, vram + 0x4000 * vram_page, vram + 0x4000 * vram_page, true);
+ } else {
+ SET_BANK(0xc000, 0xffff, wdmy, rdmy, false);
+ }
+ } else {
+ if(ipl_selected) {
+ SET_BANK(0xc000, 0xffff, ram + 0x4000, ram + 0x4000, false);
+ } else {
+ SET_BANK(0xc000, 0xffff, ram + 0xc000, ram + 0xc000, false);
+ }
+ if(vram_sel == 0xc0) {
+ SET_BANK(0xd000, 0xdfff, tvram, tvram, true);
+ }
+ }
+#else
+ if(ipl_selected) {
+ SET_BANK(0x5000, 0x7fff, wdmy, rdmy, false);
+ SET_BANK(0xd000, 0xffff, ram + 0x5000, ram + 0x5000, false);
+ } else {
+ SET_BANK(0x5000, 0x7fff, ram + 0x5000, ram + 0x5000, false);
+ SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000, false);
+ }
+ if(vram_sel == 0x80) {
+ SET_BANK(0xd000, 0xdfff, tvram, tvram, true);
+ SET_BANK(0xe000, 0xffff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);
+ } else if(vram_sel == 0xc0) {
+ SET_BANK(0x5000, 0x5fff, tvram, tvram, true);
+ SET_BANK(0x6000, 0x7fff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);
+ }
+#endif
+}
+
+void MEMORY::load_dat_image(_TCHAR* file_path)
+{
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
+ memset(ram, 0, sizeof(ram));
+ memset(vram, 0, sizeof(vram));
+ memset(tvram, 0, sizeof(tvram));
+
+ fio->Fread(ram, sizeof(ram), 1);
+ fio->Fclose();
+ vm->special_reset();
+ }
+ delete fio;
+}
+
+bool MEMORY::load_mzt_image(_TCHAR* file_path)
+{
+ bool result = false;
+ bool is_mtw = check_file_extension(file_path, _T(".mtw"));
+
+ if(is_mtw || ipl_selected) {
+ FILEIO* fio = new FILEIO();
+ if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
+ uint8 header[128];
+ fio->Fread(header, sizeof(header), 1);
+ uint16 size = header[0x12] | (header[0x13] << 8);
+ uint16 offs = header[0x14] | (header[0x15] << 8);
+
+// if(header[0] == 0x01 && (is_mtw || size > 0x7e00)) {
+ if(header[0] == 0x01 && offs == 0) {
+ memset(ram, 0, sizeof(ram));
+ memset(vram, 0, sizeof(vram));
+ memset(tvram, 0, sizeof(tvram));
+
+ fio->Fread(ram, size, 1);
+ vm->special_reset();
+ result = true;
+ }
+ fio->Fclose();
+ }
+ delete fio;
+ }
+ return result;
+}
+
+void MEMORY::draw_screen()
+{
+ // render text
+#ifndef _MZ80B
+ uint8 color = (text_color & 7) ? (text_color & 7) : 8;
+#else
+ #define color 1
+#endif
+ for(int y = 0, addr = 0; y < 200; y += 8) {
+ for(int x = 0; x < (width80 ? 80 : 40); x++) {
+ uint8 code = tvram[addr++];
+ for(int l = 0; l < 8; l++) {
+ uint8 pat = font[(code << 3) + l];
+ uint8* d = &screen_txt[y + l][x << 3];
+
+ d[0] = (pat & 0x80) ? color : 0;
+ d[1] = (pat & 0x40) ? color : 0;
+ d[2] = (pat & 0x20) ? color : 0;
+ d[3] = (pat & 0x10) ? color : 0;
+ d[4] = (pat & 0x08) ? color : 0;
+ d[5] = (pat & 0x04) ? color : 0;
+ d[6] = (pat & 0x02) ? color : 0;
+ d[7] = (pat & 0x01) ? color : 0;
+ }
+ }
+ }
+
+ // render graphics
+#ifndef _MZ80B
+ if(config.monitor_type != MONITOR_TYPE_COLOR && (vram_mask & 8)) {
+ memset(screen_gra, 0, sizeof(screen_gra));
+ } else {
+ // vram[0x0000-0x3fff] should be always blank
+ uint8 *vram_b = vram + ((vram_mask & 1) ? 0x4000 : 0);
+ uint8 *vram_r = vram + ((vram_mask & 2) ? 0x8000 : 0);
+ uint8 *vram_g = vram + ((vram_mask & 4) ? 0xc000 : 0);
+ for(int y = 0, addr = 0; y < 200; y++) {
+ for(int x = 0; x < 80; x++) {
+ uint8 b = vram_b[addr];
+ uint8 r = vram_r[addr];
+ uint8 g = vram_g[addr];
+ addr++;
+ uint8* d = &screen_gra[y][x << 3];
+
+ d[0] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
+ d[1] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
+ d[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
+ d[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
+ d[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
+ d[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
+ d[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
+ d[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
+ }
+ }
+ }
+#else
+ if(!(vram_page & 6)) {
+ memset(screen_gra, 0, sizeof(screen_gra));
+ } else {
+ // vram[0x8000-0xbfff] should be always blank
+ uint8 *vram_1 = vram + ((vram_page & 2) ? 0x0000 : 0x8000);
+ uint8 *vram_2 = vram + ((vram_page & 4) ? 0x4000 : 0x8000);
+ for(int y = 0, addr = 0; y < 200; y++) {
+ for(int x = 0; x < 40; x++) {
+ uint8 pat = vram_1[addr] | vram_2[addr];
+ addr++;
+ uint8* d = &screen_gra[y][x << 3];
+
+ d[0] = (pat & 0x01) >> 0;
+ d[1] = (pat & 0x02) >> 1;
+ d[2] = (pat & 0x04) >> 2;
+ d[3] = (pat & 0x08) >> 3;
+ d[4] = (pat & 0x10) >> 4;
+ d[5] = (pat & 0x20) >> 5;
+ d[6] = (pat & 0x40) >> 6;
+ d[7] = (pat & 0x80) >> 7;
+ }
+ }
+ }
+#endif
+
+ // copy to real screen
+ for(int y = 0; y < 200; y++) {
+ scrntype* dest0 = emu->screen_buffer(y * 2 + 0);
+ scrntype* dest1 = emu->screen_buffer(y * 2 + 1);
+ uint8* src_txt = screen_txt[y];
+ uint8* src_gra = screen_gra[y];
+#ifndef _MZ80B
+ uint8 back = (config.monitor_type == MONITOR_TYPE_COLOR) ? back_color : 0;
+
+ if(text_color & 8) {
+ // graphics > text
+ for(int x = 0; x < 640; x++) {
+ uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];
+ dest0[x] = palette_pc[gra ? gra : txt ? (txt & 7) : back];
+ }
+ } else {
+ // text > graphics
+ for(int x = 0; x < 640; x++) {
+ uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];
+ dest0[x] = palette_pc[txt ? (txt & 7) : gra ? gra : back];
+ }
+ }
+#else
+ if(width80) {
+ for(int x = 0; x < 640; x++) {
+ uint8 txt = src_txt[x], gra = src_gra[x >> 1];
+ dest0[x] = palette_pc[txt | gra];
+ }
+ } else {
+ for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
+ uint8 txt = src_txt[x], gra = src_gra[x];
+ dest0[x2] = dest0[x2 + 1] = palette_pc[txt | gra];
+ }
+ }
+#endif
+ if(config.scan_line) {
+ memset(dest1, 0, 640 * sizeof(scrntype));
+ } else {
+ memcpy(dest1, dest0, 640 * sizeof(scrntype));
+ }
+ }
+#ifndef _MZ80B
+ emu->screen_skip_line = true;
+#endif
+}
+
+#define STATE_VERSION 1
+
+void MEMORY::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ state_fio->Fwrite(ram, sizeof(ram), 1);
+ state_fio->Fwrite(vram, sizeof(vram), 1);
+ state_fio->Fwrite(tvram, sizeof(tvram), 1);
+ state_fio->FputBool(ipl_selected);
+ state_fio->FputUint8(vram_sel);
+ state_fio->FputUint8(vram_page);
+ state_fio->FputUint8(back_color);
+ state_fio->FputUint8(text_color);
+ state_fio->FputUint8(vram_mask);
+ state_fio->FputBool(width80);
+ state_fio->FputBool(reverse);
+ state_fio->FputBool(hblank);
+}
+
+bool MEMORY::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ state_fio->Fread(ram, sizeof(ram), 1);
+ state_fio->Fread(vram, sizeof(vram), 1);
+ state_fio->Fread(tvram, sizeof(tvram), 1);
+ ipl_selected = state_fio->FgetBool();
+ vram_sel = state_fio->FgetUint8();
+ vram_page = state_fio->FgetUint8();
+ back_color = state_fio->FgetUint8();
+ text_color = state_fio->FgetUint8();
+ vram_mask = state_fio->FgetUint8();
+ width80 = state_fio->FgetBool();
+ reverse = state_fio->FgetBool();
+ hblank = state_fio->FgetBool();
+
+ // post process
+ if(ipl_selected) {
+ SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);
+ SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);
+ SET_BANK(0x8000, 0xffff, ram, ram, false);
+ } else {
+ SET_BANK(0x0000, 0xffff, ram, ram, false);
+ }
+ update_vram_map();
+ update_palette();
+ return true;
+}
+