2 HITACH BASIC Master Jr Emulator 'eBASICMasterJr'
4 Author : Takeda.Toshiya
11 #include "../datarec.h"
13 #define SET_BANK(s, e, w, r) { \
14 int sb = (s) >> 11, eb = (e) >> 11; \
15 for(int i = sb; i <= eb; i++) { \
19 wbank[i] = (w) + 0x800 * (i - sb); \
24 rbank[i] = (r) + 0x800 * (i - sb); \
29 #define SOUND_VOLUME 8000
31 static const int key_table[13][4] = {
32 {0x5a, 0x41, 0x51, 0x31}, // 'Z' 'A' 'Q' '1'
33 {0x58, 0x53, 0x57, 0x32}, // 'X' 'S' 'W' '2'
34 {0x43, 0x44, 0x45, 0x33}, // 'C' 'D' 'E' '3'
35 {0x56, 0x46, 0x52, 0x34}, // 'V' 'F' 'R' '4'
36 {0x42, 0x47, 0x54, 0x35}, // 'B' 'G' 'T' '5'
37 {0x4e, 0x48, 0x59, 0x36}, // 'N' 'H' 'Y' '6'
38 {0x4d, 0x4a, 0x55, 0x37}, // 'M' 'J' 'U' '7'
39 {0xbc, 0x4b, 0x49, 0x38}, // ',' 'K' 'I' '8'
40 {0xbe, 0x4c, 0x4f, 0x39}, // '.' 'L' 'O' '9'
41 {0xbf, 0xbb, 0x50, 0x30}, // '/' ';' 'P' '0'
42 {0xe2, 0xba, 0xc0, 0xbd}, // '_' ':' '@' '-'
43 {0x20, 0xdd, 0xdb, 0xde}, // SPACE ']' '[' '^'
44 {0x00, 0x0d, 0x2e, 0xdc}, // RETURN DEL '\'
47 void MEMORY::initialize()
50 memset(ram, 0, sizeof(ram));
51 memset(basic, 0xff, sizeof(basic));
52 memset(printer, 0xff, sizeof(printer));
53 memset(monitor, 0xff, sizeof(monitor));
54 memset(rdmy, 0xff, sizeof(rdmy));
57 FILEIO* fio = new FILEIO();
58 if(fio->Fopen(create_local_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {
59 fio->Fread(basic, sizeof(basic), 1);
61 } else if(fio->Fopen(create_local_path(_T("BAS.ROM")), FILEIO_READ_BINARY)) {
62 fio->Fread(basic, sizeof(basic), 1);
65 if(fio->Fopen(create_local_path(_T("PRINTER.ROM")), FILEIO_READ_BINARY)) {
66 fio->Fread(printer, sizeof(printer), 1);
68 } else if(fio->Fopen(create_local_path(_T("PRT.ROM")), FILEIO_READ_BINARY)) {
69 fio->Fread(printer, sizeof(printer), 1);
72 if(fio->Fopen(create_local_path(_T("MONITOR.ROM")), FILEIO_READ_BINARY)) {
73 fio->Fread(monitor, sizeof(monitor), 1);
75 } else if(fio->Fopen(create_local_path(_T("MON.ROM")), FILEIO_READ_BINARY)) {
76 fio->Fread(monitor, sizeof(monitor), 1);
79 if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
80 fio->Fread(font, sizeof(font), 1);
85 SET_BANK(0x0000, 0xafff, ram, ram);
90 key_stat = emu->get_key_buffer();
93 for(int i = 0; i < 8; i++) {
94 palette_pc[i] = RGB_COLOR((i & 2) ? 0xff : 0, (i & 4) ? 0xff : 0, (i & 1) ? 0xff : 0);
98 register_frame_event(this);
106 memset(color_table, 7, sizeof(color_table));
108 back_color = mp1710_enb = 0;
111 screen_reversed = false;
116 nmi_enb = break_pressed = false;
120 sound_clock = sound_mix_clock = get_current_clock();
123 void MEMORY::write_data8(uint32_t addr, uint32_t data)
125 if((addr & 0xfe00) == 0xee00) {
127 switch(addr & 0xffff) {
129 screen_reversed = ((data & 0x80) != 0);
132 if(sound_sample != ((data >> 1) & 0x1f)) {
133 sound_accum += (double)sound_sample * get_passed_usec(sound_clock);
134 sound_clock = get_current_clock();
135 sound_sample = (data >> 1) & 0x1f;
137 d_drec->write_signal(SIG_DATAREC_MIC, ~data, 0x01);
140 key_column = data & 0x0f;
141 nmi_enb = ((data & 0x80) != 0);
142 event_frame(); // update keyboard
145 // bit4: unknown (timer on/off)
155 if((addr & 0xf800) == 0xe800 && !(memory_bank & 2)) {
157 switch(addr & 0xffff) {
162 d_pia->write_io8(addr, data);
165 // bit0-3: fore color
166 // bit4-7: back color
178 if(addr >= 0x100 && addr < 0x400) {
179 color_table[addr - 0x100] = char_color;
181 wbank[(addr >> 11) & 0x1f][addr & 0x7ff] = data;
184 uint32_t MEMORY::read_data8(uint32_t addr)
186 if((addr & 0xfe00) == 0xee00) {
188 switch(addr & 0xffff) {
191 d_drec->write_signal(SIG_DATAREC_REMOTE, addr, 0x20);
192 #if defined(USE_SOUND_FILES)
194 d_drec->write_signal(SIG_SOUNDER_ADD + DATAREC_SNDFILE_RELAY_ON, 1, 1);
196 d_drec->write_signal(SIG_SOUNDER_ADD + DATAREC_SNDFILE_RELAY_OFF, 1, 1);
201 return drec_in ? 0x80 : 0;
209 break_pressed = false;
218 if((addr & 0xf800) == 0xe800 && !(memory_bank & 2)) {
220 switch(addr & 0xffff) {
225 return d_pia->read_io8(addr);
235 return rbank[(addr >> 11) & 0x1f][addr & 0x7ff];
238 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
240 if(id == SIG_MEMORY_DATAREC_EAR) {
241 drec_in = ((data & mask) != 0);
245 void MEMORY::event_frame()
248 if(key_column < 13) {
249 if(key_stat[key_table[key_column][0]]) key_data &= ~0x01;
250 if(key_stat[key_table[key_column][1]]) key_data &= ~0x02;
251 if(key_stat[key_table[key_column][2]]) key_data &= ~0x04;
252 if(key_stat[key_table[key_column][3]]) key_data &= ~0x08;
256 // If same as bm2, not effect below keys at Qt version.
257 if(key_stat[VK_LCONTROL]) key_data &= ~0x10; //
\89p
\90\94 -> LCTRL
258 if(key_stat[VK_LSHIFT]) key_data &= ~0x20; //
\89p
\8bL
\8d\86 -> L-SHIFT
259 if(key_stat[VK_RWIN]) key_data &= ~0x40; //
\83J
\83i
\8bL
\8d\86 -> R-Win
260 if(key_stat[VK_KANA]) key_data &= ~0x80; //
\83J
\83i ->
\83J
\83^
\83J
\83i
\82Ð
\82ç
\82ª
\82È
262 // this is same as "
\93ú
\97§
\83x
\81[
\83V
\83b
\83N
\83}
\83X
\83^
\81[Jr.(MB-6885)
\83G
\83~
\83\85\83\8c\81[
\83^ bm2"
263 if(key_stat[0xa2]) key_data &= ~0x10; //
\89p
\90\94 -> L-CTRL
264 if(key_stat[0xa0]) key_data &= ~0x20; //
\89p
\8bL
\8d\86 -> L-SHIFT
265 if(key_stat[0xa1]) key_data &= ~0x40; //
\83J
\83i
\8bL
\8d\86 -> R-SHIFT
266 if(key_stat[0xa3]) key_data &= ~0x80; //
\83J
\83i -> R-CTRL
270 void MEMORY::key_down(int code)
275 d_cpu->write_signal(SIG_CPU_NMI, 1, 1);
277 break_pressed = true;
281 void MEMORY::update_bank()
283 if(memory_bank & 1) {
284 SET_BANK(0xb000, 0xdfff, ram + 0xb000, ram + 0xb000);
286 SET_BANK(0xb000, 0xdfff, wdmy, basic);
288 if(memory_bank & 2) {
289 SET_BANK(0xe000, 0xefff, ram + 0xe000, ram + 0xe000);
291 SET_BANK(0xe000, 0xe7ff, wdmy, printer);
292 SET_BANK(0xe800, 0xefff, wdmy, rdmy); // memory mapped i/o
294 if(memory_bank & 4) {
295 SET_BANK(0xf000, 0xffff, ram + 0xf000, ram + 0xf000);
297 SET_BANK(0xf000, 0xffff, wdmy, monitor);
301 void MEMORY::mix(int32_t* buffer, int cnt)
304 if(get_passed_clock(sound_mix_clock) != 0) {
305 sound_accum += (double)sound_sample * get_passed_usec(sound_clock);
306 volume = (int32_t)(SOUND_VOLUME * sound_accum / (31.0 * get_passed_usec(sound_mix_clock)));
309 sound_clock = sound_mix_clock = get_current_clock();
311 for(int i = 0; i < cnt; i++) {
312 *buffer++ = apply_volume(volume, volume_l); // L
313 *buffer++ = apply_volume(volume, volume_r); // R
317 void MEMORY::set_volume(int ch, int decibel_l, int decibel_r)
319 volume_l = decibel_to_volume(decibel_l);
320 volume_r = decibel_to_volume(decibel_r);
323 void MEMORY::draw_screen()
325 if(!(screen_mode & 0x80)) {
327 scrntype_t fore = palette_pc[screen_reversed ? 0 : 7];
328 scrntype_t back = palette_pc[screen_reversed ? 7 : 0];
331 for(int y = 0, yy = 0; y < 24; y++, yy += 8) {
332 for(int x = 0, xx = 0; x < 32; x++, xx += 8) {
334 uint8_t color = color_table[taddr];
335 if(screen_reversed) {
336 color = (color >> 4) | (color << 4);
338 fore = palette_pc[(color ) & 7];
339 back = palette_pc[(color >> 4) & 7];
341 int code = ram[taddr] << 3;
342 for(int l = 0; l < 8; l++) {
343 scrntype_t* dest = emu->get_screen_buffer(yy + l) + xx;
344 uint8_t pat = font[code + l];
345 dest[0] = (pat & 0x80) ? fore : back;
346 dest[1] = (pat & 0x40) ? fore : back;
347 dest[2] = (pat & 0x20) ? fore : back;
348 dest[3] = (pat & 0x10) ? fore : back;
349 dest[4] = (pat & 0x08) ? fore : back;
350 dest[5] = (pat & 0x04) ? fore : back;
351 dest[6] = (pat & 0x02) ? fore : back;
352 dest[7] = (pat & 0x01) ? fore : back;
359 scrntype_t fore = palette_pc[screen_reversed ? 0 : 7];
360 scrntype_t back = palette_pc[screen_reversed ? 7 : 0];
362 int gaddr = 0x900 + ((screen_mode & 0x0f) << 9);
364 for(int y = 0, yy = 0; y < 24; y++, yy += 8) {
365 for(int x = 0, xx = 0; x < 32; x++, xx += 8) {
367 uint8_t color = color_table[taddr];
368 if(screen_reversed) {
369 color = (color >> 4) | (color << 4);
371 fore = palette_pc[(color ) & 7];
372 back = palette_pc[(color >> 4) & 7];
374 for(int l = 0, ll = 0; l < 8; l++, ll += 32) {
375 scrntype_t* dest = emu->get_screen_buffer(yy + l) + xx;
376 uint8_t pat = ram[gaddr + ll];
377 dest[0] = (pat & 0x80) ? fore : back;
378 dest[1] = (pat & 0x40) ? fore : back;
379 dest[2] = (pat & 0x20) ? fore : back;
380 dest[3] = (pat & 0x10) ? fore : back;
381 dest[4] = (pat & 0x08) ? fore : back;
382 dest[5] = (pat & 0x04) ? fore : back;
383 dest[6] = (pat & 0x02) ? fore : back;
384 dest[7] = (pat & 0x01) ? fore : back;
392 // emu->screen_skip_line(false);
395 #define STATE_VERSION 1
397 void MEMORY::save_state(FILEIO* state_fio)
399 state_fio->FputUint32(STATE_VERSION);
400 state_fio->FputInt32(this_device_id);
402 state_fio->Fwrite(ram, sizeof(ram), 1);
403 state_fio->FputUint8(memory_bank);
404 state_fio->Fwrite(color_table, sizeof(color_table), 1);
405 state_fio->FputUint8(char_color);
406 state_fio->FputUint8(back_color);
407 state_fio->FputUint8(mp1710_enb);
408 state_fio->FputUint8(screen_mode);
409 state_fio->FputBool(screen_reversed);
410 state_fio->FputBool(drec_in);
411 state_fio->FputUint8(key_column);
412 state_fio->FputUint8(key_data);
413 state_fio->FputBool(nmi_enb);
414 state_fio->FputBool(break_pressed);
415 state_fio->FputUint8(sound_sample);
416 state_fio->FputDouble(sound_accum);
417 state_fio->FputUint32(sound_clock);
418 state_fio->FputUint32(sound_mix_clock);
421 bool MEMORY::load_state(FILEIO* state_fio)
423 if(state_fio->FgetUint32() != STATE_VERSION) {
426 if(state_fio->FgetInt32() != this_device_id) {
429 state_fio->Fread(ram, sizeof(ram), 1);
430 memory_bank = state_fio->FgetUint8();
431 state_fio->Fread(color_table, sizeof(color_table), 1);
432 char_color = state_fio->FgetUint8();
433 back_color = state_fio->FgetUint8();
434 mp1710_enb = state_fio->FgetUint8();
435 screen_mode = state_fio->FgetUint8();
436 screen_reversed = state_fio->FgetBool();
437 drec_in = state_fio->FgetBool();
438 key_column = state_fio->FgetUint8();
439 key_data = state_fio->FgetUint8();
440 nmi_enb = state_fio->FgetBool();
441 break_pressed = state_fio->FgetBool();
442 sound_sample = state_fio->FgetUint8();
443 sound_accum = state_fio->FgetDouble();
444 sound_clock = state_fio->FgetUint32();
445 sound_mix_clock = state_fio->FgetUint32();