2 SHARP MZ-2500 Emulator 'EmuZ-2500'
4 Author : Takeda.Toshiya
13 #define PHASE_SELECT 1
14 #define PHASE_COMMAND 2
19 #define PHASE_STATUS 7
20 #define PHASE_MESSAGE 8
22 #define STATUS_IXD 0x04
23 #define STATUS_CXD 0x08
24 #define STATUS_MSG 0x10
25 #define STATUS_BSY 0x20
26 #define STATUS_REQ 0x80
31 void MZ1E30::initialize()
34 FILEIO* fio = new FILEIO();
35 if(fio->Fopen(create_local_path(_T("MZ-1E30.ROM")), FILEIO_READ_BINARY) ||
36 fio->Fopen(create_local_path(_T("SASI.ROM")), FILEIO_READ_BINARY) ||
37 fio->Fopen(create_local_path(_T("FILE.ROM")), FILEIO_READ_BINARY)) {
38 fio->Fseek(0, FILEIO_SEEK_END);
39 if((rom_size = fio->Ftell()) > 0x1000000) {
42 rom_buffer = (uint8_t*)malloc(rom_size);
44 fio->Fseek(0, FILEIO_SEEK_SET);
45 fio->Fread(rom_buffer, rom_size, 1);
49 rom_buffer = (uint8_t*)malloc(1);
54 // open hard drive images
55 for(int i = 0; i < 2; i++) {
56 drive[i].fio = new FILEIO();
57 if(!drive[i].fio->Fopen(create_local_path(_T("HDD%d.DAT"), i + 1), FILEIO_READ_WRITE_BINARY)) {
61 drive[i].access = false;
64 // initialize sasi interface
65 memset(buffer, 0, sizeof(buffer));
66 memset(cmd, 0, sizeof(cmd));
67 memset(status_buf, 0, sizeof(status_buf));
81 void MZ1E30::release()
83 for(int i = 0; i < 2; i++) {
84 if(drive[i].fio != NULL) {
85 drive[i].fio->Fclose();
89 if(rom_buffer != NULL) {
94 void MZ1E30::write_io8(uint32_t addr, uint32_t data)
99 if(phase == PHASE_COMMAND) {
100 cmd[cmd_ptr++] = data;
104 } else if(phase == PHASE_C2) {
105 if(++status_ptr == 10) {
108 } else if(phase == PHASE_WRITE) {
109 buffer[buffer_ptr++] = data;
110 if(buffer_ptr == 256) {
130 if(phase == PHASE_SELECT) {
131 phase = PHASE_COMMAND;
134 } else if(data == 0x20) {
136 phase = PHASE_SELECT;
144 rom_address = ((addr & 0xff00) << 8) | (data << 8) | (rom_address & 0x0000ff);
149 uint32_t MZ1E30::read_io8(uint32_t addr)
153 switch(addr & 0xff) {
156 if(phase == PHASE_READ) {
157 val = buffer[buffer_ptr++];
158 if(buffer_ptr == 256) {
171 } else if(phase == PHASE_SENSE) {
172 val = status_buf[status_ptr++];
173 if(status_ptr == 4) {
176 } else if(phase == PHASE_STATUS) {
177 val = error ? 0x02 : status;
178 phase = PHASE_MESSAGE;
179 } else if(phase == PHASE_MESSAGE) {
185 val = status_irq_drq;
186 status_irq_drq &= ~STATUS_IRQ;
187 if(phase != PHASE_FREE) {
190 if(phase > PHASE_SELECT) {
193 if(phase == PHASE_COMMAND) {
196 if(phase == PHASE_SENSE) {
199 if(phase == PHASE_READ) {
202 if(phase == PHASE_STATUS) {
203 val |= STATUS_IXD | STATUS_CXD;
205 if(phase == PHASE_MESSAGE) {
206 val |= STATUS_IXD | STATUS_CXD | STATUS_MSG;
211 rom_address = (rom_address & 0xffff00) | ((addr & 0xff00) >> 8);
212 if(rom_address < rom_size) {
213 return rom_buffer[rom_address];
220 void MZ1E30::write_dma_io8(uint32_t addr, uint32_t data)
222 write_io8(0xa4, data);
225 uint32_t MZ1E30::read_dma_io8(uint32_t addr)
227 return read_io8(0xa4);
230 uint32_t MZ1E30::read_signal(int ch)
233 uint32_t stat = (drive[0].access ? 1 : 0) | (drive[1].access ? 2 : 0);
234 drive[0].access = drive[1].access = false;
238 void MZ1E30::check_cmd()
240 unit = (cmd[1] >> 5) & 1;
245 if(drive[unit].fio != NULL) {
255 if(drive[unit].fio != NULL) {
265 // request sense status
267 status_buf[0] = error;
268 status_buf[1] = (uint8_t)((unit << 5) | ((sector >> 16) & 0x1f));
269 status_buf[2] = (uint8_t)(sector >> 8);
270 status_buf[3] = (uint8_t)sector;
283 sector = cmd[1] & 0x1f;
284 sector = (sector << 8) | cmd[2];
285 sector = (sector << 8) | cmd[3];
296 sector = cmd[1] & 0x1f;
297 sector = (sector << 8) | cmd[2];
298 sector = (sector << 8) | cmd[3];
301 if(blocks != 0 && seek(unit)) {
310 sector = cmd[1] & 0x1f;
311 sector = (sector << 8) | cmd[2];
312 sector = (sector << 8) | cmd[3];
315 if(blocks != 0 && seek(unit)) {
318 memset(buffer, 0, sizeof(buffer));
325 sector = cmd[1] & 0x1f;
326 sector = (sector << 8) | cmd[2];
327 sector = (sector << 8) | cmd[3];
345 void MZ1E30::set_status(uint8_t err)
349 phase = PHASE_STATUS;
351 status_irq_drq |= STATUS_IRQ;
353 vm->register_event(this, 0, 10, false, NULL);
357 void MZ1E30::event_callback(int event_id, int err)
360 phase = PHASE_STATUS;
362 status_irq_drq |= STATUS_IRQ;
366 void MZ1E30::set_drq(bool flag)
369 status_irq_drq |= STATUS_DRQ;
371 status_irq_drq &= ~STATUS_DRQ;
375 bool MZ1E30::seek(int drv)
377 memset(buffer, 0, sizeof(buffer));
379 if(drive[drv & 1].fio == NULL) {
382 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
385 if(drive[drv & 1].fio->Fread(buffer, 256, 1) != 1) {
388 drive[drv & 1].access = true;
392 bool MZ1E30::flush(int drv)
394 if(drive[drv & 1].fio == NULL) {
397 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
400 if(drive[drv & 1].fio->Fwrite(buffer, 256, 1) != 1) {
403 drive[drv & 1].access = true;
407 bool MZ1E30::format(int drv)
409 if(drive[drv & 1].fio == NULL) {
412 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
416 memset(buffer, 0, sizeof(buffer));
417 for(int i = 0; i < 33; i++) {
418 if(drive[drv & 1].fio->Fwrite(buffer, 256, 1) != 1) {
421 drive[drv & 1].access = true;
426 #define STATE_VERSION 1
428 void MZ1E30::save_state(FILEIO* state_fio)
430 state_fio->FputUint32(STATE_VERSION);
431 state_fio->FputInt32(this_device_id);
433 state_fio->FputUint32(rom_address);
434 state_fio->Fwrite(buffer, sizeof(buffer), 1);
435 state_fio->FputInt32(phase);
436 state_fio->FputInt32(sector);
437 state_fio->FputInt32(blocks);
438 state_fio->Fwrite(cmd, sizeof(cmd), 1);
439 state_fio->FputInt32(cmd_ptr);
440 state_fio->FputInt32(unit);
441 state_fio->FputInt32(buffer_ptr);
442 state_fio->FputUint8(status);
443 state_fio->FputUint8(status_irq_drq);
444 state_fio->FputUint8(error);
445 state_fio->Fwrite(status_buf, sizeof(status_buf), 1);
446 state_fio->FputInt32(status_ptr);
447 state_fio->FputUint8(datareg);
450 bool MZ1E30::load_state(FILEIO* state_fio)
452 if(state_fio->FgetUint32() != STATE_VERSION) {
455 if(state_fio->FgetInt32() != this_device_id) {
458 rom_address = state_fio->FgetUint32();
459 state_fio->Fread(buffer, sizeof(buffer), 1);
460 phase = state_fio->FgetInt32();
461 sector = state_fio->FgetInt32();
462 blocks = state_fio->FgetInt32();
463 state_fio->Fread(cmd, sizeof(cmd), 1);
464 cmd_ptr = state_fio->FgetInt32();
465 unit = state_fio->FgetInt32();
466 buffer_ptr = state_fio->FgetInt32();
467 status = state_fio->FgetUint8();
468 status_irq_drq = state_fio->FgetUint8();
469 error = state_fio->FgetUint8();
470 state_fio->Fread(status_buf, sizeof(status_buf), 1);
471 status_ptr = state_fio->FgetInt32();
472 datareg = state_fio->FgetUint8();