2 SHARP MZ-2500 Emulator 'EmuZ-2500'
\r
4 Author : Takeda.Toshiya
\r
11 #include "../../fileio.h"
\r
13 #define PHASE_FREE 0
\r
14 #define PHASE_SELECT 1
\r
15 #define PHASE_COMMAND 2
\r
17 #define PHASE_SENSE 4
\r
18 #define PHASE_READ 5
\r
19 #define PHASE_WRITE 6
\r
20 #define PHASE_STATUS 7
\r
21 #define PHASE_MESSAGE 8
\r
23 #define STATUS_IXD 0x04
\r
24 #define STATUS_CXD 0x08
\r
25 #define STATUS_MSG 0x10
\r
26 #define STATUS_BSY 0x20
\r
27 #define STATUS_REQ 0x80
\r
29 #define STATUS_IRQ 0
\r
30 #define STATUS_DRQ 0
\r
32 void MZ1E30::initialize()
\r
35 FILEIO* fio = new FILEIO();
\r
36 if(fio->Fopen(emu->bios_path(_T("MZ-1E30.ROM")), FILEIO_READ_BINARY) ||
\r
37 fio->Fopen(emu->bios_path(_T("SASI.ROM")), FILEIO_READ_BINARY) ||
\r
38 fio->Fopen(emu->bios_path(_T("FILE.ROM")), FILEIO_READ_BINARY)) {
\r
39 fio->Fseek(0, FILEIO_SEEK_END);
\r
40 if((rom_size = fio->Ftell()) > 0x1000000) {
\r
41 rom_size = 0x1000000;
\r
43 rom_buffer = (uint8*)malloc(rom_size);
\r
45 fio->Fseek(0, FILEIO_SEEK_SET);
\r
46 fio->Fread(rom_buffer, rom_size, 1);
\r
50 rom_buffer = (uint8*)malloc(1);
\r
55 // open hard drive images
\r
56 for(int i = 0; i < 2; i++) {
\r
57 _TCHAR file_name[_MAX_PATH];
\r
58 _stprintf_s(file_name, _MAX_PATH, _T("HDD%d.DAT"), i + 1);
\r
60 drive[i].fio = new FILEIO();
\r
61 if(!drive[i].fio->Fopen(emu->bios_path(file_name), FILEIO_READ_WRITE_BINARY)) {
\r
62 delete drive[i].fio;
\r
63 drive[i].fio = NULL;
\r
65 drive[i].access = false;
\r
68 // initialize sasi interface
\r
69 memset(buffer, 0, sizeof(buffer));
\r
70 memset(cmd, 0, sizeof(cmd));
\r
71 memset(status_buf, 0, sizeof(status_buf));
\r
85 void MZ1E30::release()
\r
87 for(int i = 0; i < 2; i++) {
\r
88 if(drive[i].fio != NULL) {
\r
89 drive[i].fio->Fclose();
\r
90 delete drive[i].fio;
\r
93 if(rom_buffer != NULL) {
\r
98 void MZ1E30::write_io8(uint32 addr, uint32 data)
\r
100 switch(addr & 0xff) {
\r
103 if(phase == PHASE_COMMAND) {
\r
104 cmd[cmd_ptr++] = data;
\r
108 } else if(phase == PHASE_C2) {
\r
109 if(++status_ptr == 10) {
\r
112 } else if(phase == PHASE_WRITE) {
\r
113 buffer[buffer_ptr++] = data;
\r
114 if(buffer_ptr == 256) {
\r
134 if(phase == PHASE_SELECT) {
\r
135 phase = PHASE_COMMAND;
\r
138 } else if(data == 0x20) {
\r
140 phase = PHASE_SELECT;
\r
142 phase = PHASE_FREE;
\r
148 rom_address = ((addr & 0xff00) << 8) | (data << 8) | (rom_address & 0x0000ff);
\r
153 uint32 MZ1E30::read_io8(uint32 addr)
\r
157 switch(addr & 0xff) {
\r
160 if(phase == PHASE_READ) {
\r
161 val = buffer[buffer_ptr++];
\r
162 if(buffer_ptr == 256) {
\r
175 } else if(phase == PHASE_SENSE) {
\r
176 val = status_buf[status_ptr++];
\r
177 if(status_ptr == 4) {
\r
180 } else if(phase == PHASE_STATUS) {
\r
181 val = error ? 0x02 : status;
\r
182 phase = PHASE_MESSAGE;
\r
183 } else if(phase == PHASE_MESSAGE) {
\r
184 phase = PHASE_FREE;
\r
189 val = status_irq_drq;
\r
190 status_irq_drq &= ~STATUS_IRQ;
\r
191 if(phase != PHASE_FREE) {
\r
194 if(phase > PHASE_SELECT) {
\r
197 if(phase == PHASE_COMMAND) {
\r
200 if(phase == PHASE_SENSE) {
\r
203 if(phase == PHASE_READ) {
\r
206 if(phase == PHASE_STATUS) {
\r
207 val |= STATUS_IXD | STATUS_CXD;
\r
209 if(phase == PHASE_MESSAGE) {
\r
210 val |= STATUS_IXD | STATUS_CXD | STATUS_MSG;
\r
215 rom_address = (rom_address & 0xffff00) | ((addr & 0xff00) >> 8);
\r
216 if(rom_address < rom_size) {
\r
217 return rom_buffer[rom_address];
\r
224 void MZ1E30::write_dma_io8(uint32 addr, uint32 data)
\r
226 write_io8(0xa4, data);
\r
229 uint32 MZ1E30::read_dma_io8(uint32 addr)
\r
231 return read_io8(0xa4);
\r
234 uint32 MZ1E30::read_signal(int ch)
\r
236 // get access status
\r
237 uint32 stat = (drive[0].access ? 0x10 : 0) | (drive[1].access ? 0x20 : 0);
\r
238 drive[0].access = drive[1].access = false;
\r
242 void MZ1E30::check_cmd()
\r
244 unit = (cmd[1] >> 5) & 1;
\r
248 // test drive ready
\r
249 if(drive[unit].fio != NULL) {
\r
259 if(drive[unit].fio != NULL) {
\r
269 // request sense status
\r
270 phase = PHASE_SENSE;
\r
271 status_buf[0] = error;
\r
272 status_buf[1] = (uint8)((unit << 5) | ((sector >> 16) & 0x1f));
\r
273 status_buf[2] = (uint8)(sector >> 8);
\r
274 status_buf[3] = (uint8)sector;
\r
287 sector = cmd[1] & 0x1f;
\r
288 sector = (sector << 8) | cmd[2];
\r
289 sector = (sector << 8) | cmd[3];
\r
300 sector = cmd[1] & 0x1f;
\r
301 sector = (sector << 8) | cmd[2];
\r
302 sector = (sector << 8) | cmd[3];
\r
305 if(blocks != 0 && seek(unit)) {
\r
306 phase = PHASE_READ;
\r
314 sector = cmd[1] & 0x1f;
\r
315 sector = (sector << 8) | cmd[2];
\r
316 sector = (sector << 8) | cmd[3];
\r
319 if(blocks != 0 && seek(unit)) {
\r
320 phase = PHASE_WRITE;
\r
322 memset(buffer, 0, sizeof(buffer));
\r
329 sector = cmd[1] & 0x1f;
\r
330 sector = (sector << 8) | cmd[2];
\r
331 sector = (sector << 8) | cmd[3];
\r
349 void MZ1E30::set_status(uint8 err)
\r
353 phase = PHASE_STATUS;
\r
355 status_irq_drq |= STATUS_IRQ;
\r
357 vm->register_event(this, 0, 10, false, NULL);
\r
361 void MZ1E30::event_callback(int event_id, int err)
\r
364 phase = PHASE_STATUS;
\r
366 status_irq_drq |= STATUS_IRQ;
\r
370 void MZ1E30::set_drq(bool flag)
\r
373 status_irq_drq |= STATUS_DRQ;
\r
375 status_irq_drq &= ~STATUS_DRQ;
\r
379 bool MZ1E30::seek(int drv)
\r
381 memset(buffer, 0, sizeof(buffer));
\r
383 if(drive[drv & 1].fio == NULL) {
\r
386 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
\r
389 if(drive[drv & 1].fio->Fread(buffer, 256, 1) != 1) {
\r
392 drive[drv & 1].access = true;
\r
396 bool MZ1E30::flush(int drv)
\r
398 if(drive[drv & 1].fio == NULL) {
\r
401 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
\r
404 if(drive[drv & 1].fio->Fwrite(buffer, 256, 1) != 1) {
\r
407 drive[drv & 1].access = true;
\r
411 bool MZ1E30::format(int drv)
\r
413 if(drive[drv & 1].fio == NULL) {
\r
416 if(drive[drv & 1].fio->Fseek(sector * 256, FILEIO_SEEK_SET) != 0) {
\r
419 // format 33 blocks
\r
420 memset(buffer, 0, sizeof(buffer));
\r
421 for(int i = 0; i < 33; i++) {
\r
422 if(drive[drv & 1].fio->Fwrite(buffer, 256, 1) != 1) {
\r
425 drive[drv & 1].access = true;
\r
430 #define STATE_VERSION 1
\r
432 void MZ1E30::save_state(FILEIO* state_fio)
\r
434 state_fio->FputUint32(STATE_VERSION);
\r
435 state_fio->FputInt32(this_device_id);
\r
437 state_fio->FputUint32(rom_address);
\r
438 state_fio->Fwrite(buffer, sizeof(buffer), 1);
\r
439 state_fio->FputInt32(phase);
\r
440 state_fio->FputInt32(sector);
\r
441 state_fio->FputInt32(blocks);
\r
442 state_fio->Fwrite(cmd, sizeof(cmd), 1);
\r
443 state_fio->FputInt32(cmd_ptr);
\r
444 state_fio->FputInt32(unit);
\r
445 state_fio->FputInt32(buffer_ptr);
\r
446 state_fio->FputUint8(status);
\r
447 state_fio->FputUint8(status_irq_drq);
\r
448 state_fio->FputUint8(error);
\r
449 state_fio->Fwrite(status_buf, sizeof(status_buf), 1);
\r
450 state_fio->FputInt32(status_ptr);
\r
451 state_fio->FputUint8(datareg);
\r
454 bool MZ1E30::load_state(FILEIO* state_fio)
\r
456 if(state_fio->FgetUint32() != STATE_VERSION) {
\r
459 if(state_fio->FgetInt32() != this_device_id) {
\r
462 rom_address = state_fio->FgetUint32();
\r
463 state_fio->Fread(buffer, sizeof(buffer), 1);
\r
464 phase = state_fio->FgetInt32();
\r
465 sector = state_fio->FgetInt32();
\r
466 blocks = state_fio->FgetInt32();
\r
467 state_fio->Fread(cmd, sizeof(cmd), 1);
\r
468 cmd_ptr = state_fio->FgetInt32();
\r
469 unit = state_fio->FgetInt32();
\r
470 buffer_ptr = state_fio->FgetInt32();
\r
471 status = state_fio->FgetUint8();
\r
472 status_irq_drq = state_fio->FgetUint8();
\r
473 error = state_fio->FgetUint8();
\r
474 state_fio->Fread(status_buf, sizeof(status_buf), 1);
\r
475 status_ptr = state_fio->FgetInt32();
\r
476 datareg = state_fio->FgetUint8();
\r