2 SHARP MZ-80B Emulator 'EmuZ-80B'
\r
3 SHARP MZ-2200 Emulator 'EmuZ-2200'
\r
5 Author : Takeda.Toshiya
\r
11 #include "memory80b.h"
\r
12 #include "../i8255.h"
\r
14 #include "../../fileio.h"
\r
16 #define EVENT_HBLANK 0
\r
18 #define MONITOR_TYPE_COLOR 0
\r
19 #define MONITOR_TYPE_GREEN 1
\r
21 #define SET_BANK(s, e, w, r, v) { \
\r
22 int sb = (s) >> 11, eb = (e) >> 11; \
\r
23 for(int i = sb; i <= eb; i++) { \
\r
27 wbank[i] = (w) + 0x800 * (i - sb); \
\r
32 rbank[i] = (r) + 0x800 * (i - sb); \
\r
38 void MEMORY::initialize()
\r
41 memset(rdmy, 0xff, sizeof(rdmy));
\r
42 memset(ram, 0, sizeof(ram));
\r
43 memset(vram, 0, sizeof(vram));
\r
44 memset(tvram, 0, sizeof(tvram));
\r
45 memset(ipl, 0xff, sizeof(ipl));
\r
47 FILEIO* fio = new FILEIO();
\r
48 if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
\r
49 fio->Fread(ipl, sizeof(ipl), 1);
\r
52 if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
\r
53 fio->Fread(font, sizeof(font), 1);
\r
58 vram_sel = vram_page = 0;
\r
62 text_color = vram_mask = 7;
\r
63 width80 = reverse = false;
\r
66 register_vline_event(this);
\r
69 void MEMORY::reset()
\r
72 SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);
\r
73 SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);
\r
74 SET_BANK(0x8000, 0xffff, ram, ram, false);
\r
76 ipl_selected = true;
\r
80 void MEMORY::special_reset()
\r
83 SET_BANK(0x0000, 0xffff, ram, ram, false);
\r
85 ipl_selected = false;
\r
89 void MEMORY::write_data8(uint32 addr, uint32 data)
\r
92 if(!hblank && is_vram[addr >> 11]) {
\r
93 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
\r
95 wbank[addr >> 11][addr & 0x7ff] = data;
\r
98 uint32 MEMORY::read_data8(uint32 addr)
\r
101 if(!hblank && is_vram[addr >> 11]) {
\r
102 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
\r
104 return rbank[addr >> 11][addr & 0x7ff];
\r
107 uint32 MEMORY::fetch_op(uint32 addr, int *wait)
\r
110 *wait = (ipl_selected && addr < 0x800);
\r
111 return rbank[addr >> 11][addr & 0x7ff];
\r
114 void MEMORY::write_io8(uint32 addr, uint32 data)
\r
116 switch(addr & 0xff) {
\r
119 back_color = data & 7;
\r
128 if(vram_page != (data & 3)) {
\r
129 vram_page = data & 3;
\r
130 if(vram_sel == 0x80) {
\r
140 if(vram_page != (data & 7)) {
\r
141 uint8 prev_page = vram_page;
\r
142 vram_page = data & 7;
\r
143 if((prev_page & 1) != (vram_page & 1) && (vram_sel == 0x80 || vram_sel == 0xc0)) {
\r
152 void MEMORY::write_signal(int id, uint32 data, uint32 mask)
\r
154 if(id == SIG_MEMORY_VRAM_SEL) {
\r
155 if(vram_sel != (data & mask)) {
\r
156 vram_sel = data & mask;
\r
159 } else if(id == SIG_CRTC_WIDTH80) {
\r
160 width80 = ((data & mask) != 0);
\r
161 } else if(id == SIG_CRTC_REVERSE) {
\r
162 reverse = ((data & mask) == 0);
\r
164 if(config.monitor_type != MONITOR_TYPE_COLOR)
\r
170 void MEMORY::event_vline(int v, int clock)
\r
173 d_pio->write_signal(SIG_I8255_PORT_B, 1, 1);
\r
174 } else if(v == 200) {
\r
175 d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);
\r
179 register_event_by_clock(this, EVENT_HBLANK, 184, false, NULL);
\r
183 void MEMORY::event_callback(int event_id, int err)
\r
185 if(event_id == EVENT_HBLANK) {
\r
187 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
\r
192 void MEMORY::update_config()
\r
198 void MEMORY::update_palette()
\r
201 if(config.monitor_type == MONITOR_TYPE_COLOR) {
\r
202 for(int i = 0; i < 8; i++) {
\r
203 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
\r
208 for(int i = 0; i < 8; i++) {
\r
209 palette_pc[i] = RGB_COLOR(0, i ? 0 : 255, 0);
\r
212 for(int i = 0; i < 8; i++) {
\r
213 palette_pc[i] = RGB_COLOR(0, i ? 255 : 0, 0);
\r
218 void MEMORY::update_vram_map()
\r
221 if(vram_sel == 0x80) {
\r
223 SET_BANK(0xc000, 0xffff, vram + 0x4000 * vram_page, vram + 0x4000 * vram_page, true);
\r
225 SET_BANK(0xc000, 0xffff, wdmy, rdmy, false);
\r
229 SET_BANK(0xc000, 0xffff, ram + 0x4000, ram + 0x4000, false);
\r
231 SET_BANK(0xc000, 0xffff, ram + 0xc000, ram + 0xc000, false);
\r
233 if(vram_sel == 0xc0) {
\r
234 SET_BANK(0xd000, 0xdfff, tvram, tvram, true);
\r
239 SET_BANK(0x5000, 0x7fff, wdmy, rdmy, false);
\r
240 SET_BANK(0xd000, 0xffff, ram + 0x5000, ram + 0x5000, false);
\r
242 SET_BANK(0x5000, 0x7fff, ram + 0x5000, ram + 0x5000, false);
\r
243 SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000, false);
\r
245 if(vram_sel == 0x80) {
\r
246 SET_BANK(0xd000, 0xdfff, tvram, tvram, true);
\r
247 SET_BANK(0xe000, 0xffff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);
\r
248 } else if(vram_sel == 0xc0) {
\r
249 SET_BANK(0x5000, 0x5fff, tvram, tvram, true);
\r
250 SET_BANK(0x6000, 0x7fff, vram + 0x4000 * (vram_page & 1), vram + 0x4000 * (vram_page & 1), true);
\r
255 void MEMORY::load_dat_image(_TCHAR* file_path)
\r
257 FILEIO* fio = new FILEIO();
\r
258 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
\r
259 memset(ram, 0, sizeof(ram));
\r
260 memset(vram, 0, sizeof(vram));
\r
261 memset(tvram, 0, sizeof(tvram));
\r
263 fio->Fread(ram, sizeof(ram), 1);
\r
265 vm->special_reset();
\r
270 bool MEMORY::load_mzt_image(_TCHAR* file_path)
\r
272 bool result = false;
\r
273 bool is_mtw = check_file_extension(file_path, _T(".mtw"));
\r
275 if(is_mtw || ipl_selected) {
\r
276 FILEIO* fio = new FILEIO();
\r
277 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
\r
279 fio->Fread(header, sizeof(header), 1);
\r
280 uint16 size = header[0x12] | (header[0x13] << 8);
\r
281 uint16 offs = header[0x14] | (header[0x15] << 8);
\r
283 // if(header[0] == 0x01 && (is_mtw || size > 0x7e00)) {
\r
284 if(header[0] == 0x01 && offs == 0) {
\r
285 memset(ram, 0, sizeof(ram));
\r
286 memset(vram, 0, sizeof(vram));
\r
287 memset(tvram, 0, sizeof(tvram));
\r
289 fio->Fread(ram, size, 1);
\r
290 vm->special_reset();
\r
300 void MEMORY::draw_screen()
\r
304 uint8 color = (text_color & 7) ? (text_color & 7) : 8;
\r
308 for(int y = 0, addr = 0; y < 200; y += 8) {
\r
309 for(int x = 0; x < (width80 ? 80 : 40); x++) {
\r
310 uint8 code = tvram[addr++];
\r
311 for(int l = 0; l < 8; l++) {
\r
312 uint8 pat = font[(code << 3) + l];
\r
313 uint8* d = &screen_txt[y + l][x << 3];
\r
315 d[0] = (pat & 0x80) ? color : 0;
\r
316 d[1] = (pat & 0x40) ? color : 0;
\r
317 d[2] = (pat & 0x20) ? color : 0;
\r
318 d[3] = (pat & 0x10) ? color : 0;
\r
319 d[4] = (pat & 0x08) ? color : 0;
\r
320 d[5] = (pat & 0x04) ? color : 0;
\r
321 d[6] = (pat & 0x02) ? color : 0;
\r
322 d[7] = (pat & 0x01) ? color : 0;
\r
329 if(config.monitor_type != MONITOR_TYPE_COLOR && (vram_mask & 8)) {
\r
330 memset(screen_gra, 0, sizeof(screen_gra));
\r
332 // vram[0x0000-0x3fff] should be always blank
\r
333 uint8 *vram_b = vram + ((vram_mask & 1) ? 0x4000 : 0);
\r
334 uint8 *vram_r = vram + ((vram_mask & 2) ? 0x8000 : 0);
\r
335 uint8 *vram_g = vram + ((vram_mask & 4) ? 0xc000 : 0);
\r
336 for(int y = 0, addr = 0; y < 200; y++) {
\r
337 for(int x = 0; x < 80; x++) {
\r
338 uint8 b = vram_b[addr];
\r
339 uint8 r = vram_r[addr];
\r
340 uint8 g = vram_g[addr];
\r
342 uint8* d = &screen_gra[y][x << 3];
\r
344 d[0] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
\r
345 d[1] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
\r
346 d[2] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
\r
347 d[3] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
\r
348 d[4] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
\r
349 d[5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
\r
350 d[6] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
\r
351 d[7] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
\r
356 if(!(vram_page & 6)) {
\r
357 memset(screen_gra, 0, sizeof(screen_gra));
\r
359 // vram[0x8000-0xbfff] should be always blank
\r
360 uint8 *vram_1 = vram + ((vram_page & 2) ? 0x0000 : 0x8000);
\r
361 uint8 *vram_2 = vram + ((vram_page & 4) ? 0x4000 : 0x8000);
\r
362 for(int y = 0, addr = 0; y < 200; y++) {
\r
363 for(int x = 0; x < 40; x++) {
\r
364 uint8 pat = vram_1[addr] | vram_2[addr];
\r
366 uint8* d = &screen_gra[y][x << 3];
\r
368 d[0] = (pat & 0x01) >> 0;
\r
369 d[1] = (pat & 0x02) >> 1;
\r
370 d[2] = (pat & 0x04) >> 2;
\r
371 d[3] = (pat & 0x08) >> 3;
\r
372 d[4] = (pat & 0x10) >> 4;
\r
373 d[5] = (pat & 0x20) >> 5;
\r
374 d[6] = (pat & 0x40) >> 6;
\r
375 d[7] = (pat & 0x80) >> 7;
\r
381 // copy to real screen
\r
382 for(int y = 0; y < 200; y++) {
\r
383 scrntype* dest0 = emu->screen_buffer(y * 2 + 0);
\r
384 scrntype* dest1 = emu->screen_buffer(y * 2 + 1);
\r
385 uint8* src_txt = screen_txt[y];
\r
386 uint8* src_gra = screen_gra[y];
\r
388 uint8 back = (config.monitor_type == MONITOR_TYPE_COLOR) ? back_color : 0;
\r
390 if(text_color & 8) {
\r
392 for(int x = 0; x < 640; x++) {
\r
393 uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];
\r
394 dest0[x] = palette_pc[gra ? gra : txt ? (txt & 7) : back];
\r
398 for(int x = 0; x < 640; x++) {
\r
399 uint8 txt = src_txt[width80 ? x : (x >> 1)], gra = src_gra[x];
\r
400 dest0[x] = palette_pc[txt ? (txt & 7) : gra ? gra : back];
\r
405 for(int x = 0; x < 640; x++) {
\r
406 uint8 txt = src_txt[x], gra = src_gra[x >> 1];
\r
407 dest0[x] = palette_pc[txt | gra];
\r
410 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
\r
411 uint8 txt = src_txt[x], gra = src_gra[x];
\r
412 dest0[x2] = dest0[x2 + 1] = palette_pc[txt | gra];
\r
416 if(config.scan_line) {
\r
417 memset(dest1, 0, 640 * sizeof(scrntype));
\r
419 memcpy(dest1, dest0, 640 * sizeof(scrntype));
\r
423 emu->screen_skip_line = true;
\r
427 #define STATE_VERSION 1
\r
429 void MEMORY::save_state(FILEIO* state_fio)
\r
431 state_fio->FputUint32(STATE_VERSION);
\r
432 state_fio->FputInt32(this_device_id);
\r
434 state_fio->Fwrite(ram, sizeof(ram), 1);
\r
435 state_fio->Fwrite(vram, sizeof(vram), 1);
\r
436 state_fio->Fwrite(tvram, sizeof(tvram), 1);
\r
437 state_fio->FputBool(ipl_selected);
\r
438 state_fio->FputUint8(vram_sel);
\r
439 state_fio->FputUint8(vram_page);
\r
440 state_fio->FputUint8(back_color);
\r
441 state_fio->FputUint8(text_color);
\r
442 state_fio->FputUint8(vram_mask);
\r
443 state_fio->FputBool(width80);
\r
444 state_fio->FputBool(reverse);
\r
445 state_fio->FputBool(hblank);
\r
448 bool MEMORY::load_state(FILEIO* state_fio)
\r
450 if(state_fio->FgetUint32() != STATE_VERSION) {
\r
453 if(state_fio->FgetInt32() != this_device_id) {
\r
456 state_fio->Fread(ram, sizeof(ram), 1);
\r
457 state_fio->Fread(vram, sizeof(vram), 1);
\r
458 state_fio->Fread(tvram, sizeof(tvram), 1);
\r
459 ipl_selected = state_fio->FgetBool();
\r
460 vram_sel = state_fio->FgetUint8();
\r
461 vram_page = state_fio->FgetUint8();
\r
462 back_color = state_fio->FgetUint8();
\r
463 text_color = state_fio->FgetUint8();
\r
464 vram_mask = state_fio->FgetUint8();
\r
465 width80 = state_fio->FgetBool();
\r
466 reverse = state_fio->FgetBool();
\r
467 hblank = state_fio->FgetBool();
\r
470 SET_BANK(0x0000, 0x07ff, wdmy, ipl, false);
\r
471 SET_BANK(0x0800, 0x7fff, wdmy, rdmy, false);
\r
472 SET_BANK(0x8000, 0xffff, ram, ram, false);
\r
474 SET_BANK(0x0000, 0xffff, ram, ram, false);
\r