OSDN Git Service

[General][VM] Merge upstream 2015-08-09.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr50 / bios.cpp
1 /*
2         FUJITSU FMR-30 Emulator 'eFMR-30'
3         FUJITSU FMR-50 Emulator 'eFMR-50'
4         FUJITSU FMR-60 Emulator 'eFMR-60'
5
6         Author : Takeda.Toshiya
7         Date   : 2008.10.06 -
8
9         [ bios ]
10 */
11
12 #include "bios.h"
13 #include "../disk.h"
14
15 // regs
16 #define AX      regs[0]
17 #define CX      regs[1]
18 #define DX      regs[2]
19 #define BX      regs[3]
20 #define SP      regs[4]
21 #define BP      regs[5]
22 #define SI      regs[6]
23 #define DI      regs[7]
24
25 #define AL      regs8[0]
26 #define AH      regs8[1]
27 #define CL      regs8[2]
28 #define CH      regs8[3]
29 #define DL      regs8[4]
30 #define DH      regs8[5]
31 #define BL      regs8[6]
32 #define BH      regs8[7]
33 #define SPL     regs8[8]
34 #define SPH     regs8[9]
35 #define BPL     regs8[10]
36 #define BPH     regs8[11]
37 #define SIL     regs8[12]
38 #define SIH     regs8[13]
39 #define DIL     regs8[14]
40 #define DIH     regs8[15]
41
42 // sregs
43 #define ES      sregs[0]
44 #define CS      sregs[1]
45 #define SS      sregs[2]
46 #define DS      sregs[3]
47
48 // error
49 #define ERR_FDD_NOTREADY        1
50 #define ERR_FDD_PROTECTED       2
51 #define ERR_FDD_DELETED         4
52 #define ERR_FDD_NOTFOUND        8
53 #define ERR_FDD_CRCERROR        0x10
54 #define ERR_SCSI_NOTREADY       1
55 #define ERR_SCSI_PARAMERROR     2
56 #define ERR_SCSI_NOTCONNECTED   4
57 #define ERR_MEMCARD_NOTREADY    1
58 #define ERR_MEMCARD_PROTECTED   2
59 #define ERR_MEMCARD_PARAMERROR  0x200
60
61 #if defined(_FMR30)
62 // FMR-30
63 #define CMOS_SIZE       0x2000
64 #define VRAM_SIZE       0x20000
65 #define IPL_SIZE        0x10000
66 #define IPL_ID          '2'
67 #elif defined(_FMR50)
68 // FMR-50
69 #define CMOS_SIZE       0x800
70 #define VRAM_SIZE       0x40000
71 #define IPL_SIZE        0x4000
72 #define IPL_ID          '1'
73 #elif defined(_FMR60)
74 // FMR-60
75 #define CMOS_SIZE       0x800
76 #define VRAM_SIZE       0x80000
77 #define IPL_SIZE        0x4000
78 #define IPL_ID          '1'
79 #endif
80
81 #define BLOCK_SIZE      512
82
83 static const int iotable[][2] = {
84 #ifdef _FMR30
85         {0x0100, 0x19}, // pic
86         {0x0101, 0x40},
87         {0x0101, 0x80},
88         {0x0101, 0x01},
89         {0x0101, 0xff},
90         {0x0108, 0x19},
91         {0x010a, 0x48},
92         {0x010a, 0x07},
93         {0x010a, 0x01},
94         {0x010a, 0xff},
95         {0x0042, 0x00}, // timer
96         {0x0133, 0x30},
97         {0x0130, 0xa0},
98         {0x0130, 0x86},
99         {0x000b, 0x02}, // sio
100         {0x0009, 0x00},
101         {0x0009, 0x50},
102         {0x0009, 0x7f},
103         {0x0009, 0x15},
104         {0x0013, 0x02},
105         {0x001d, 0x02}, // memory
106         {0x001e, 0x00},
107         {0x0040, 0x9f}, // psg
108         {0x0040, 0xbf},
109         {0x0040, 0xdf},
110         {0x0040, 0xff},
111         {0x0300, 0x01}, // lcdc
112         {0x0302, 0x50},
113         {0x0300, 0x09},
114         {0x0302, 0x0f},
115         {0x0300, 0x0a},
116         {0x0302, 0x20},
117         {0x0300, 0x0b},
118         {0x0302, 0x0d},
119         {0x0300, 0x0c},
120         {0x0302, 0x00},
121         {0x0300, 0x0d},
122         {0x0302, 0x00},
123         {0x0300, 0x0e},
124         {0x0302, 0x00},
125         {0x0300, 0x0f},
126         {0x0302, 0x00},
127         {0x0300, 0x11},
128         {0x0302, 0xc7},
129         {0x0300, 0x1d},
130         {0x0302, 0x00},
131         {0x0308, 0x63},
132         {0x0309, 0x00},
133         {0x030a, 0x00},
134 #else
135         {0x0060, 0x00}, // timer
136         {0x0604, 0x00}, // keyboard
137         {0x0000, 0x19}, // pic
138         {0x0002, 0x40},
139         {0x0002, 0x80},
140         {0x0002, 0x0d},
141         {0x0002, 0xfe},
142         {0x0010, 0x19},
143         {0x0012, 0x48},
144         {0x0012, 0x87},
145         {0x0012, 0x09},
146         {0x0012, 0xff},
147         {0x0000, 0x20},
148         {0x0046, 0x36}, // pit
149         {0x0040, 0x00},
150         {0x0040, 0x78},
151         {0x0404, 0x00}, // memory
152         {0x0500, 0x00}, // crtc
153         {0x0502, 0x35},
154         {0x0500, 0x01},
155         {0x0502, 0x28},
156         {0x0500, 0x02},
157         {0x0502, 0x2c},
158         {0x0500, 0x03},
159         {0x0502, 0x04},
160         {0x0500, 0x04},
161         {0x0502, 0x1a},
162         {0x0500, 0x05},
163         {0x0502, 0x08},
164         {0x0500, 0x06},
165         {0x0502, 0x19},
166         {0x0500, 0x07},
167         {0x0502, 0x19},
168         {0x0500, 0x08},
169         {0x0502, 0x00},
170         {0x0500, 0x09},
171         {0x0502, 0x0f},
172         {0x0500, 0x0a},
173         {0x0502, 0x20},
174         {0x0500, 0x0b},
175         {0x0502, 0x1e},
176         {0x0500, 0x0c},
177         {0x0502, 0x00},
178         {0x0500, 0x0d},
179         {0x0502, 0x00},
180         {0x0500, 0x0e},
181         {0x0502, 0x00},
182         {0x0500, 0x0f},
183         {0x0502, 0x00},
184         {0x0500, 0x10},
185         {0x0502, 0x00},
186         {0x0500, 0x11},
187         {0x0502, 0x00},
188         {0x0500, 0x1e},
189         {0x0502, 0x00},
190         {0x0500, 0x1f},
191         {0x0502, 0x00},
192         {0xfd98, 0x00}, // palette
193         {0xfd99, 0x01},
194         {0xfd9a, 0x02},
195         {0xfd9b, 0x03},
196         {0xfd9c, 0x04},
197         {0xfd9d, 0x05},
198         {0xfd9e, 0x06},
199         {0xfd9f, 0x07},
200         {0xfda0, 0x0f}, // video
201 #endif
202         {-1, -1}
203 };
204
205 // cmos: $000-
206 static const uint8 cmos_t[] = {
207 #ifdef _FMR30
208         0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
209         0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
210         0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x44,0x45,0x42,0x20,0x18,0x05,
211         0x00,0x01,0x01,0xfa,0x44,0x45,0x53,0x4b,0x18,0x06,0x32,0x00,0x00,0x00,0x00,0x00,
212         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
213         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
214         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
215         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
216         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
217         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
218         0x4a,0x06,0x7b,0x19,0x97,0x62,0x79,0x41
219 #else
220         0x01,0xff,0x42,0x4f,0x4f,0x54,0xa8,0x00,0x40,0x00,0x01,0xfe,0x53,0x45,0x54,0x55,
221         0xe8,0x00,0x00,0x01,0x01,0xfd,0x4c,0x4f,0x47,0x20,0xe8,0x01,0x10,0x03,0x01,0xfc,
222         0x4f,0x41,0x53,0x59,0xf8,0x04,0x20,0x00,0x01,0xfb,0x58,0x45,0x4e,0x49,0x18,0x05,
223         0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
225         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
226         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
227         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
228         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
229         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230 //      0x28,0x05,0x99,0x02,0xe1,0xe1,0x79,0x41
231         0x28,0x05,0x99,0x02,0x00,0x00,0x79,0x41
232 #endif
233 };
234 // FMR-30: cmos $1fd0-
235 // FMR-50: cmos $7d0-
236 static const uint8 cmos_b[] = {
237 #ifdef _FMR30
238         0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0xff,0xff,0xff,0xff,0xff,
239         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240         0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
241 #else
242         0x00,0x00,0x01,0x02,0x03,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
243         0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
244         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
245 #endif
246 };
247
248 // boot message
249 static const uint8 msg_c[] = {
250         0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
251         0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
252         0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,
253         0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07,0xff,0x47,0xff,0x07
254 };
255
256 // '\83V\83X\83e\83\80\82ð\83Z\83b\83g\82µ\82Ä\82­\82¾\82³\82¢'
257 static const uint8 msg_k[] = {
258         0x25,0x37,0x00,0x00,0x25,0x39,0x00,0x00,0x25,0x46,0x00,0x00,0x25,0x60,0x00,0x00,
259         0x24,0x72,0x00,0x00,0x25,0x3b,0x00,0x00,0x25,0x43,0x00,0x00,0x25,0x48,0x00,0x00,
260         0x24,0x37,0x00,0x00,0x24,0x46,0x00,0x00,0x24,0x2f,0x00,0x00,0x24,0x40,0x00,0x00,
261         0x24,0x35,0x00,0x00,0x24,0x24,0x00,0x00,0x21,0x21,0x00,0x00
262 };
263
264 void BIOS::initialize()
265 {
266         // check ipl
267         disk_pc1 = disk_pc2 = cmos_pc = wait_pc = -1;
268         ipl_loaded = false;
269         
270         FILEIO* fio = new FILEIO();
271         if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
272                 fio->Fread(buffer, sizeof(buffer), 1);
273                 fio->Fclose();
274                 
275                 uint32 addr = 0xfffc4;
276                 if(buffer[addr & (IPL_SIZE - 1)] == 0xea) {
277                         int ofs = buffer[++addr & (IPL_SIZE - 1)];
278                         ofs |= buffer[++addr & (IPL_SIZE - 1)] << 8;
279                         int seg = buffer[++addr & (IPL_SIZE - 1)];
280                         seg |= buffer[++addr & (IPL_SIZE - 1)] << 8;
281                         disk_pc1 = addr = ofs + (seg << 4);
282                 }
283                 if(buffer[addr & (IPL_SIZE - 1)] == 0xea) {
284                         int ofs = buffer[++addr & (IPL_SIZE - 1)];
285                         ofs |= buffer[++addr & (IPL_SIZE - 1)] << 8;
286                         int seg = buffer[++addr & (IPL_SIZE - 1)];
287                         seg |= buffer[++addr & (IPL_SIZE - 1)] << 8;
288                         disk_pc2 = ofs + (seg << 4);
289                 }
290                 ipl_loaded = true;
291         } else {
292                 // use pseudo ipl
293                 cmos_pc = 0xfffc9;
294                 wait_pc = 0xfffd3;
295                 
296                 // register event
297                 register_frame_event(this);
298         }
299         
300         // init scsi
301         memset(scsi_blocks, 0, sizeof(scsi_blocks));
302         for(int i = 0; i < MAX_SCSI; i++) {
303                 _stprintf_s(scsi_path[i], _MAX_PATH, _T("%sSCSI%d.DAT"), emu->application_path(), i);
304                 if(fio->Fopen(scsi_path[i], FILEIO_READ_BINARY)) {
305                         fio->Fseek(0, FILEIO_SEEK_END);
306                         scsi_blocks[i] = fio->Ftell() / BLOCK_SIZE;
307                         fio->Fclose();
308                 }
309         }
310         
311         // init memcard
312         memset(memcard_blocks, 0, sizeof(memcard_blocks));
313         for(int i = 0; i < MAX_MEMCARD; i++) {
314                 _stprintf_s(memcard_path[i], _MAX_PATH, _T("%sMEMCARD%d.DAT"), emu->application_path(), i);
315                 if(fio->Fopen(memcard_path[i], FILEIO_READ_BINARY)) {
316                         fio->Fseek(0, FILEIO_SEEK_END);
317                         memcard_blocks[i] = fio->Ftell() / BLOCK_SIZE;
318                         memcard_protected[i] = FILEIO::IsFileProtected(memcard_path[i]);
319                         fio->Fclose();
320                 }
321         }
322         delete fio;
323 }
324
325 void BIOS::reset()
326 {
327         for(int i = 0; i < MAX_DRIVE; i++) {
328                 access_fdd[i] = false;
329         }
330         access_scsi = false;
331         secnum = 1;
332         powmode = 0;
333         timeout = 0;
334 }
335
336 void BIOS::event_frame()
337 {
338         timeout++;
339 }
340
341 bool BIOS::bios_call_i86(uint32 PC, uint16 regs[], uint16 sregs[], int32* ZeroFlag, int32* CarryFlag)
342 {
343         uint8 *regs8 = (uint8 *)regs;
344         int drv = AL & 0xf;
345         
346         if(PC == 0xfffc4 || PC == disk_pc1 || PC == disk_pc2) {
347                 // disk bios
348 #ifdef _DEBUG_LOG
349                 emu->out_debug_log(_T("%6x\tDISK BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
350 #endif
351 //              if(ipl_loaded && (AL & 0xf0) == 0x20) {
352                         // don't use pseudo bios for floppy drive
353 //                      return false;
354 //              }
355 //              if(!((AL & 0xf0) == 0x20 || (AL & 0xf0) == 0x50 || (AL & 0xf0) == 0xb0)) {
356                         // target drive is not floppy, memcard and scsi hard drive
357 //                      return false;
358 //              }
359                 if(AH == 2) {
360                         // drive status
361                         if((AL & 0xf0) == 0x20) {
362                                 // floppy
363                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
364                                         AH = 0x80;
365                                         CX = ERR_FDD_NOTREADY;
366                                         *CarryFlag = 1;
367                                         return true;
368                                 }
369                                 AH = 0;
370                                 DL = 4;
371                                 if(disk[drv]->write_protected) {
372                                         DL |= 2;
373                                 }
374                                 CX = 0;
375                                 *CarryFlag = 0;
376                                 return true;
377                         }
378                         if((AL & 0xf0) == 0x50) {
379                                 // memcard
380                                 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
381                                         AH = 0x80;
382                                         CX = ERR_MEMCARD_NOTREADY;
383                                         *CarryFlag = 1;
384                                         return true;
385                                 }
386                                 AH = 0;
387                                 AL = 2;
388                                 DL = memcard_protected[drv] ? 2 : 0;
389                                 CX = 0;
390                                 *CarryFlag = 0;
391                                 return true;
392                         }
393                         if((AL & 0xf0) == 0xb0) {
394                                 // scsi
395                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
396                                         AH = 0x80;
397                                         CX = ERR_SCSI_NOTCONNECTED;
398                                         *CarryFlag = 1;
399                                         return true;
400                                 }
401                                 AH = 0;
402                                 AL = (BLOCK_SIZE == 128) ? 0 : (BLOCK_SIZE == 256) ? 1 : (BLOCK_SIZE == 512) ? 2 : 3;
403                                 BX = scsi_blocks[drv] >> 16;
404                                 DX = scsi_blocks[drv] & 0xffff;
405                                 CX = 0;
406                                 *CarryFlag = 0;
407                                 return true;
408                         }
409                         AH = 2;
410                         *CarryFlag = 1;
411                         return true;
412                 } else if(AH == 3 || AH == 4) {
413                         // restore/seek
414                         if((AL & 0xf0) == 0x20) {
415                                 // floppy
416                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
417                                         AH = 0x80;
418                                         CX = ERR_FDD_NOTREADY;
419                                         *CarryFlag = 1;
420                                         return true;
421                                 }
422                                 AH = 0;
423                                 CX = 0;
424                                 *CarryFlag = 0;
425                                 return true;
426                         }
427                         if((AL & 0xf0) == 0xb0) {
428                                 // scsi
429                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
430                                         AH = 0x80;
431                                         CX = ERR_SCSI_NOTCONNECTED;
432                                         *CarryFlag = 1;
433                                         return true;
434                                 }
435                                 AH = 0;
436                                 CX = 0;
437                                 *CarryFlag = 0;
438                                 return true;
439                         }
440                         AH = 2;
441                         *CarryFlag = 1;
442                         return true;
443                 } else if(AH == 5) {
444                         // read sectors
445                         if((AL & 0xf0) == 0x20) {
446                                 // floppy
447                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
448                                         AH = 0x80;
449                                         CX = ERR_FDD_NOTREADY;
450                                         *CarryFlag = 1;
451                                         return true;
452                                 }
453                                 // get initial c/h/r
454                                 int ofs = DS * 16 + DI;
455                                 int trk = CX;
456                                 int hed = DH & 1;
457                                 int sct = DL;
458                                 while(BX > 0) {
459                                         // search sector
460                                         disk[drv]->get_track(trk, hed);
461                                         access_fdd[drv] = true;
462                                         secnum = sct;
463                                         if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
464                                                 AH = 0x80;
465                                                 CX = ERR_FDD_NOTFOUND;
466                                                 *CarryFlag = 1;
467                                                 return true;
468                                         }
469                                         // check id crc error
470                                         if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
471                                                 AH = 0x80;
472                                                 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
473                                                 *CarryFlag = 1;
474                                                 return true;
475                                         }
476                                         // check deleted mark
477                                         if(disk[drv]->deleted) {
478                                                 AH = 0x80;
479                                                 CX = ERR_FDD_DELETED;
480                                                 *CarryFlag = 1;
481                                                 return true;
482                                         }
483                                         // data transfer
484                                         for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
485                                                 d_mem->write_data8(ofs++, disk[drv]->sector[i]);
486                                         }
487                                         BX--;
488                                         // check data crc error
489                                         if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
490                                                 AH = 0x80;
491                                                 CX = ERR_FDD_CRCERROR;
492                                                 *CarryFlag = 1;
493                                                 return true;
494                                         }
495                                         // update c/h/r
496                                         if(++sct > disk[drv]->sector_num.sd) {
497                                                 sct = 1;
498                                                 if(++hed > 1) {
499                                                         hed = 0;
500                                                         ++trk;
501                                                 }
502                                         }
503                                 }
504                                 AH = 0;
505                                 CX = 0;
506                                 *CarryFlag = 0;
507                                 return true;
508                         }
509                         if((AL & 0xf0) == 0x50) {
510                                 // memcard
511                                 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
512                                         AH = 0x80;
513                                         CX = ERR_MEMCARD_NOTREADY;
514                                         *CarryFlag = 1;
515                                         return true;
516                                 }
517                                 FILEIO* fio = new FILEIO();
518                                 if(!fio->Fopen(memcard_path[drv], FILEIO_READ_BINARY)) {
519                                         AH = 0x80;
520                                         CX = ERR_MEMCARD_NOTREADY;
521                                         *CarryFlag = 1;
522                                         delete fio;
523                                         return true;
524                                 }
525                                 // get params
526                                 int ofs = DS * 16 + DI;
527                                 int block = (CL << 16) | DX;
528                                 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
529                                 while(BX > 0) {
530                                         // check block
531                                         if(!(block++ < memcard_blocks[drv])) {
532                                                 AH = 0x80;
533                                                 CX = ERR_MEMCARD_PARAMERROR;
534                                                 *CarryFlag = 1;
535                                                 fio->Fclose();
536                                                 delete fio;
537                                                 return true;
538                                         }
539                                         // data transfer
540                                         fio->Fread(buffer, BLOCK_SIZE, 1);
541                                         for(int i = 0; i < BLOCK_SIZE; i++) {
542                                                 d_mem->write_data8(ofs++, buffer[i]);
543                                         }
544                                         BX--;
545                                 }
546                                 AH = 0;
547                                 CX = 0;
548                                 *CarryFlag = 0;
549                                 fio->Fclose();
550                                 delete fio;
551                                 return true;
552                         }
553                         if((AL & 0xf0) == 0xb0) {
554                                 // scsi
555                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
556                                         AH = 0x80;
557                                         CX = ERR_SCSI_NOTCONNECTED;
558                                         *CarryFlag = 1;
559                                         return true;
560                                 }
561                                 FILEIO* fio = new FILEIO();
562                                 if(!fio->Fopen(scsi_path[drv], FILEIO_READ_BINARY)) {
563                                         AH = 0x80;
564                                         CX = ERR_SCSI_NOTREADY;
565                                         *CarryFlag = 1;
566                                         delete fio;
567                                         return true;
568                                 }
569                                 // get params
570                                 int ofs = DS * 16 + DI;
571                                 int block = (CL << 16) | DX;
572                                 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
573                                 while(BX > 0) {
574                                         // check block
575                                         access_scsi = true;
576                                         if(!(block++ < scsi_blocks[drv])) {
577                                                 AH = 0x80;
578                                                 CX = ERR_SCSI_PARAMERROR;
579                                                 *CarryFlag = 1;
580                                                 fio->Fclose();
581                                                 delete fio;
582                                                 return true;
583                                         }
584                                         // data transfer
585                                         fio->Fread(buffer, BLOCK_SIZE, 1);
586                                         for(int i = 0; i < BLOCK_SIZE; i++) {
587                                                 d_mem->write_data8(ofs++, buffer[i]);
588                                         }
589                                         BX--;
590                                 }
591                                 AH = 0;
592                                 CX = 0;
593                                 *CarryFlag = 0;
594                                 fio->Fclose();
595                                 delete fio;
596                                 return true;
597                         }
598                         AH = 2;
599                         *CarryFlag = 1;
600                         return true;
601                 } else if(AH == 6) {
602                         // write sectors
603                         if((AL & 0xf0) == 0x20) {
604                                 // floppy
605                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
606                                         AH = 0x80;
607                                         CX = ERR_FDD_NOTREADY;
608                                         *CarryFlag = 1;
609                                         return true;
610                                 }
611                                 if(disk[drv]->write_protected) {
612                                         AH = 0x80;
613                                         CX = ERR_FDD_PROTECTED;
614                                         *CarryFlag = 1;
615                                         return true;
616                                 }
617                                 // get initial c/h/r
618                                 int ofs = DS * 16 + DI;
619                                 int trk = CX;
620                                 int hed = DH & 1;
621                                 int sct = DL;
622                                 while(BX > 0) {
623                                         // search sector
624                                         disk[drv]->get_track(trk, hed);
625                                         access_fdd[drv] = true;
626                                         secnum = sct;
627                                         if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
628                                                 AH = 0x80;
629                                                 CX = ERR_FDD_NOTFOUND;
630                                                 *CarryFlag = 1;
631                                                 return true;
632                                         }
633                                         // check id crc error
634                                         if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
635                                                 AH = 0x80;
636                                                 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
637                                                 *CarryFlag = 1;
638                                                 return true;
639                                         }
640                                         // data transfer
641                                         for(int i = 0; i < disk[drv]->sector_size.sd; i++) {
642                                                 disk[drv]->sector[i] = d_mem->read_data8(ofs++);
643                                         }
644                                         BX--;
645                                         // clear deleted mark and data crc error
646                                         disk[drv]->set_deleted(false);
647                                         disk[drv]->set_data_crc_error(false);
648                                         // update c/h/r
649                                         if(++sct > disk[drv]->sector_num.sd) {
650                                                 sct = 1;
651                                                 if(++hed > 1) {
652                                                         hed = 0;
653                                                         ++trk;
654                                                 }
655                                         }
656                                 }
657                                 AH = 0;
658                                 CX = 0;
659                                 *CarryFlag = 0;
660                                 return true;
661                         }
662                         if((AL & 0xf0) == 0x50) {
663                                 // memcard
664                                 if(!(drv < MAX_MEMCARD && memcard_blocks[drv])) {
665                                         AH = 0x80;
666                                         CX = ERR_MEMCARD_NOTREADY;
667                                         *CarryFlag = 1;
668                                         return true;
669                                 }
670                                 if(memcard_protected[drv]) {
671                                         AH = 0x80;
672                                         CX = ERR_MEMCARD_PROTECTED;
673                                         *CarryFlag = 1;
674                                         return true;
675                                 }
676                                 FILEIO* fio = new FILEIO();
677                                 if(!fio->Fopen(memcard_path[drv], FILEIO_READ_WRITE_BINARY)) {
678                                         AH = 0x80;
679                                         CX = ERR_MEMCARD_NOTREADY;
680                                         *CarryFlag = 1;
681                                         delete fio;
682                                         return true;
683                                 }
684                                 // get params
685                                 int ofs = DS * 16 + DI;
686                                 int block = (CL << 16) | DX;
687                                 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
688                                 while(BX > 0) {
689                                         // check block
690                                         access_scsi = true;
691                                         if(!(block++ < scsi_blocks[drv])) {
692                                                 AH = 0x80;
693                                                 CX = ERR_MEMCARD_PARAMERROR;
694                                                 *CarryFlag = 1;
695                                                 fio->Fclose();
696                                                 delete fio;
697                                                 return true;
698                                         }
699                                         // data transfer
700                                         for(int i = 0; i < BLOCK_SIZE; i++) {
701                                                 buffer[i] = d_mem->read_data8(ofs++);
702                                         }
703                                         fio->Fwrite(buffer, BLOCK_SIZE, 1);
704                                         BX--;
705                                 }
706                                 AH = 0;
707                                 CX = 0;
708                                 *CarryFlag = 0;
709                                 fio->Fclose();
710                                 delete fio;
711                                 return true;
712                         }
713                         if((AL & 0xf0) == 0xb0) {
714                                 // scsi
715                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
716                                         AH = 0x80;
717                                         CX = ERR_SCSI_NOTCONNECTED;
718                                         *CarryFlag = 1;
719                                         return true;
720                                 }
721                                 FILEIO* fio = new FILEIO();
722                                 if(!fio->Fopen(scsi_path[drv], FILEIO_READ_WRITE_BINARY)) {
723                                         AH = 0x80;
724                                         CX = ERR_SCSI_NOTREADY;
725                                         *CarryFlag = 1;
726                                         delete fio;
727                                         return true;
728                                 }
729                                 // get params
730                                 int ofs = DS * 16 + DI;
731                                 int block = (CL << 16) | DX;
732                                 fio->Fseek(block * BLOCK_SIZE, FILEIO_SEEK_SET);
733                                 while(BX > 0) {
734                                         // check block
735                                         access_scsi = true;
736                                         if(!(block++ < scsi_blocks[drv])) {
737                                                 AH = 0x80;
738                                                 CX = ERR_SCSI_PARAMERROR;
739                                                 *CarryFlag = 1;
740                                                 fio->Fclose();
741                                                 delete fio;
742                                                 return true;
743                                         }
744                                         // data transfer
745                                         for(int i = 0; i < BLOCK_SIZE; i++) {
746                                                 buffer[i] = d_mem->read_data8(ofs++);
747                                         }
748                                         fio->Fwrite(buffer, BLOCK_SIZE, 1);
749                                         BX--;
750                                 }
751                                 AH = 0;
752                                 CX = 0;
753                                 *CarryFlag = 0;
754                                 fio->Fclose();
755                                 delete fio;
756                                 return true;
757                         }
758                         AH = 2;
759                         *CarryFlag = 1;
760                         return true;
761                 } else if(AH == 7) {
762                         // verify sectors
763                         if((AL & 0xf0) == 0x20) {
764                                 // floppy
765                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
766                                         AH = 0x80;
767                                         CX = ERR_FDD_NOTREADY;
768                                         *CarryFlag = 1;
769                                         return true;
770                                 }
771                                 // get initial c/h/r
772                                 int trk = CX;
773                                 int hed = DH & 1;
774                                 int sct = DL;
775                                 while(BX > 0) {
776                                         // search sector
777                                         disk[drv]->get_track(trk, hed);
778                                         access_fdd[drv] = true;
779                                         secnum = sct;
780                                         if(!disk[drv]->get_sector(trk, hed, sct - 1)) {
781                                                 AH = 0x80;
782                                                 CX = ERR_FDD_NOTFOUND;
783                                                 *CarryFlag = 1;
784                                                 return true;
785                                         }
786                                         // check id crc error
787                                         if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
788                                                 AH = 0x80;
789                                                 CX = ERR_FDD_NOTFOUND | ERR_FDD_CRCERROR;
790                                                 *CarryFlag = 1;
791                                                 return true;
792                                         }
793                                         // FIXME: verify
794                                         BX--;
795                                         // check data crc error
796                                         if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
797                                                 AH = 0x80;
798                                                 CX = ERR_FDD_CRCERROR;
799                                                 *CarryFlag = 1;
800                                                 return true;
801                                         }
802                                         // update c/h/r
803                                         if(++sct > disk[drv]->sector_num.sd) {
804                                                 sct = 1;
805                                                 if(++hed > 1) {
806                                                         hed = 0;
807                                                         ++trk;
808                                                 }
809                                         }
810                                 }
811                                 AH = 0;
812                                 CX = 0;
813                                 *CarryFlag = 0;
814                                 return true;
815                         }
816                         if((AL & 0xf0) == 0xb0) {
817                                 // scsi
818                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
819                                         AH = 0x80;
820                                         CX = ERR_SCSI_NOTCONNECTED;
821                                         *CarryFlag = 1;
822                                         return true;
823                                 }
824                                 // get params
825                                 int block = (CL << 16) | DX;
826                                 while(BX > 0) {
827                                         // check block
828                                         access_scsi = true;
829                                         if(!(block++ < scsi_blocks[drv])) {
830                                                 AH = 0x80;
831                                                 CX = ERR_SCSI_PARAMERROR;
832                                                 *CarryFlag = 1;
833                                                 return true;
834                                         }
835                                         BX--;
836                                 }
837                                 AH = 0;
838                                 CX = 0;
839                                 *CarryFlag = 0;
840                                 return true;
841                         }
842                         AH = 2;
843                         *CarryFlag = 1;
844                         return true;
845                 } else if(AH == 8) {
846                         // reset hard drive controller
847                         AH = 0;
848                         CX = 0;
849                         *CarryFlag = 0;
850                         return true;
851                 } else if(AH == 9) {
852                         // read id
853                         if((AL & 0xf0) == 0x20) {
854                                 // floppy
855                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
856                                         AH = 0x80;
857                                         CX = ERR_FDD_NOTREADY;
858                                         *CarryFlag = 1;
859                                         return true;
860                                 }
861                                 // get initial c/h
862                                 int ofs = DS * 16 + DI;
863                                 int trk = CX;
864                                 int hed = DH & 1;
865                                 // search sector
866                                 disk[drv]->get_track(trk, hed);
867                                 access_fdd[drv] = true;
868                                 if(++secnum > disk[drv]->sector_num.sd) {
869                                         secnum = 1;
870                                 }
871                                 if(!disk[drv]->get_sector(trk, hed, secnum - 1)) {
872                                         AH = 0x80;
873                                         CX = ERR_FDD_NOTFOUND;
874                                         *CarryFlag = 1;
875                                         return true;
876                                 }
877                                 // data transfer
878                                 for(int i = 0; i < 6; i++) {
879                                         d_mem->write_data8(ofs++, disk[drv]->id[i]);
880                                 }
881                                 // check id crc error
882                                 if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
883                                         AH = 0x80;
884                                         CX = ERR_FDD_CRCERROR;
885                                         *CarryFlag = 1;
886                                         return true;
887                                 }
888                                 AH = 0;
889                                 CX = 0;
890                                 *CarryFlag = 0;
891                                 return true;
892                         }
893                         AH = 2;
894                         *CarryFlag = 1;
895                         return true;
896                 } else if(AH == 0xa) {
897                         // format track
898                         if((AL & 0xf0) == 0x20) {
899                                 // floppy
900                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
901                                         AH = 0x80;
902                                         CX = ERR_FDD_NOTREADY;
903                                         *CarryFlag = 1;
904                                         return true;
905                                 }
906                                 // get initial c/h
907                                 int ofs = DS * 16 + DI;
908                                 int trk = CX;
909                                 int hed = DH & 1;
910                                 // format track
911                                 disk[drv]->format_track(trk, hed);
912                                 access_fdd[drv] = true;
913                                 bool id_written = false;
914                                 bool sector_found = false;
915                                 int sector_length, sector_index;
916                                 for(int index = 0; index < disk[drv]->get_track_size(); index++) {
917                                         uint8 datareg = d_mem->read_data8(ofs++);
918                                         if(datareg == 0xf5) {
919                                                 // write a1h in missing clock
920                                         } else if(datareg == 0xf6) {
921                                                 // write c2h in missing clock
922                                         } else if(datareg == 0xf7) {
923                                                 // write crc
924                                                 if(!id_written) {
925                                                         // insert new sector with data crc error
926 write_id:
927                                                         id_written = true;
928                                                         sector_found = false;
929                                                         uint8 c = disk[drv]->track[index - 4];
930                                                         uint8 h = disk[drv]->track[index - 3];
931                                                         uint8 r = disk[drv]->track[index - 2];
932                                                         uint8 n = disk[drv]->track[index - 1];
933                                                         sector_length = 0x80 << (n & 3);
934                                                         sector_index = 0;
935                                                         disk[drv]->insert_sector(c, h, r, n, false, true, 0xe5, sector_length);
936                                                 } else if(sector_found) {
937                                                         // clear data crc error if all sector data are written
938                                                         disk[drv]->set_data_crc_error(false);
939                                                         id_written = false;
940                                                 } else {
941                                                         // data mark of current sector is not written
942                                                         disk[drv]->set_data_mark_missing();
943                                                         goto write_id;
944                                                 }
945                                         } else if(id_written) {
946                                                 if(sector_found) {
947                                                         // sector data
948                                                         if(sector_index < sector_length) {
949                                                                 disk[drv]->sector[sector_index] = datareg;
950                                                         }
951                                                         sector_index++;
952                                                 } else if(datareg == 0xf8 || datareg == 0xfb) {
953                                                         // data mark
954                                                         disk[drv]->set_deleted(datareg == 0xf8);
955                                                         sector_found = true;
956                                                 }
957                                         }
958                                         disk[drv]->track[index] = datareg;
959                                 }
960                                 AH = 0;
961                                 CX = 0;
962                                 *CarryFlag = 0;
963                                 return true;
964                         }
965                         AH = 2;
966                         *CarryFlag = 1;
967                         return true;
968                 } else if(AH == 0xd) {
969                         // read error
970                         AH = 0;
971                         CX = 0;
972                         *CarryFlag = 0;
973                         return true;
974                 } else if(AH == 0xe) {
975                         // disk change ???
976                         if((AL & 0xf0) == 0x20) {
977                                 // floppy
978                                 if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
979                                         AH = 0;
980                                         CX = 0;
981                                         DL = 1;
982                                         *CarryFlag = 0;
983                                         return true;
984                                 }
985                                 AH = 0;
986                                 CX = 0;
987                                 DL = disk[drv]->changed ? 1 : 0;
988                                 disk[drv]->changed = false;
989                                 *CarryFlag = 0;
990                                 return true;
991                         }
992                         if((AL & 0xf0) == 0xb0) {
993                                 // scsi
994                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
995                                         AH = 3; // ???
996                                         CX = 0;
997                                         *CarryFlag = 1;
998                                         return true;
999                                 }
1000                                 AH = 0;
1001                                 CX = 0;
1002                                 *CarryFlag = 0;
1003                                 return true;
1004                         }
1005                         AH = 2;
1006                         CX = 0;
1007                         *CarryFlag = 1;
1008                         return true;
1009                 } else if(AH == 0xfa) {
1010                         // unknown
1011                         if((AL & 0xf0) == 0x20) {
1012                                 // floppy
1013                                 AH = 1;
1014                                 CX = 0;
1015                                 *CarryFlag = 1;
1016                                 return true;
1017                         }
1018                         if((AL & 0xf0) == 0xb0) {
1019                                 // scsi
1020                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
1021                                         AH = 0x80;
1022                                         CX = ERR_SCSI_NOTCONNECTED;
1023                                         *CarryFlag = 1;
1024                                         return true;
1025                                 }
1026                                 AH = 0;
1027                                 CX = 0;
1028                                 *CarryFlag = 0;
1029                                 return true;
1030                         }
1031                         AH = 2;
1032                         *CarryFlag = 1;
1033                         return true;
1034                 } else if(AH == 0xfd) {
1035                         // unknown
1036                         if((AL & 0xf0) == 0x20) {
1037                                 // floppy
1038                                 AH = 1;
1039                                 CX = 0;
1040                                 *CarryFlag = 1;
1041                                 return true;
1042                         }
1043                         if((AL & 0xf0) == 0xb0) {
1044                                 // scsi
1045                                 if(!(drv < MAX_SCSI && scsi_blocks[drv])) {
1046                                         AH = 0;
1047                                         CX = 0x200;     // ???
1048                                         *CarryFlag = 0;
1049                                         return true;
1050                                 }
1051                                 AH = 2;
1052                                 CX = 0;
1053                                 *CarryFlag = 1;
1054                                 return true;
1055                         }
1056                         AH = 2;
1057                         CX = 0;
1058                         *CarryFlag = 1;
1059                         return true;
1060                 } else if(AH == 0x80) {
1061                         // pseudo bios: init i/o
1062                         for(int i = 0;; i++) {
1063                                 if(iotable[i][0] < 0) {
1064                                         break;
1065                                 }
1066                                 d_io->write_io8(iotable[i][0], iotable[i][1]);
1067                         }
1068                         // init cmos
1069                         memset(cmos, 0, CMOS_SIZE);
1070                         memcpy(cmos, cmos_t, sizeof(cmos_t));
1071                         memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
1072                         // init int vector
1073                         for(int i = 0, ofs = 0; i < 256; i++) {
1074                                 // int vector = ffff:0008
1075                                 d_mem->write_data16(ofs + 0, 0x0008);
1076                                 d_mem->write_data16(ofs + 2, 0xffff);
1077                                 ofs += 4;
1078                         }
1079                         // init screen
1080                         memset(vram, 0, VRAM_SIZE);
1081 #ifdef _FMR60
1082                         memset(cvram, 0, 0x2000);
1083                         memset(avram, 0, 0x2000);
1084 #else
1085                         memset(cvram, 0, 0x1000);
1086                         memset(kvram, 0, 0x1000);
1087                         memcpy(cvram + 0xf00, msg_c, sizeof(msg_c));
1088                         memcpy(kvram + 0xf00, msg_k, sizeof(msg_k));
1089 #endif
1090                         *CarryFlag = 0;
1091                         return true;
1092                 } else if(AH == 0x81) {
1093                         // pseudo bios: boot from fdd #0
1094                         *ZeroFlag = (timeout > (int)(FRAMES_PER_SEC * 4));
1095                         if(!disk[0]->inserted) {
1096                                 *CarryFlag = 1;
1097                                 return true;
1098                         }
1099                         // load ipl
1100                         disk[0]->get_track(0, 0);
1101                         access_fdd[0] = true;
1102                         if(!disk[0]->get_sector(0, 0, 0)) {
1103                                 *CarryFlag = 1;
1104                                 return true;
1105                         }
1106                         for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1107                                 buffer[i] = disk[0]->sector[i];
1108                         }
1109                         // check ipl
1110                         if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1111                                 *CarryFlag = 1;
1112                                 return true;
1113                         }
1114                         // data transfer
1115                         for(int i = 0; i < disk[0]->sector_size.sd; i++) {
1116                                 d_mem->write_data8(0xb0000 + i, buffer[i]);
1117                         }
1118                         // clear screen
1119 #ifdef _FMR60
1120                         memset(cvram, 0, 0x2000);
1121                         memset(avram, 0, 0x2000);
1122 #else
1123                         memset(cvram, 0, 0x1000);
1124                         memset(kvram, 0, 0x1000);
1125 #endif
1126                         // set result
1127                         AX = 0xff;
1128                         CX = 0;
1129                         BX = 2;
1130                         *ZeroFlag = 1;
1131                         *CarryFlag = 0;
1132                         return true;
1133                 } else if(AH == 0x82) {
1134                         // pseudo bios: boot from scsi-hdd #0
1135                         timeout = 0;
1136                         if(!scsi_blocks[0]) {
1137                                 *CarryFlag = 1;
1138                                 return true;
1139                         }
1140                         FILEIO* fio = new FILEIO();
1141                         if(!fio->Fopen(scsi_path[drv], FILEIO_READ_BINARY)) {
1142                                 *CarryFlag = 1;
1143                                 delete fio;
1144                                 return true;
1145                         }
1146                         // load ipl
1147                         access_scsi = true;
1148                         fio->Fread(buffer, BLOCK_SIZE * 4, 1);
1149                         fio->Fclose();
1150                         delete fio;
1151                         // check ipl
1152                         if(!(buffer[0] == 'I' && buffer[1] == 'P' && buffer[2] == 'L' && buffer[3] == IPL_ID)) {
1153                                 *CarryFlag = 1;
1154                                 return true;
1155                         }
1156                         // data transfer
1157                         for(int i = 0; i < BLOCK_SIZE * 4; i++) {
1158                                 d_mem->write_data8(0xb0000 + i, buffer[i]);
1159                         }
1160                         // clear screen
1161 #ifdef _FMR60
1162                         memset(cvram, 0, 0x2000);
1163                         memset(avram, 0, 0x2000);
1164 #else
1165                         memset(cvram, 0, 0x1000);
1166                         memset(kvram, 0, 0x1000);
1167 #endif
1168                         // set result
1169                         AX = 0xffff;
1170                         CX = 0;
1171                         BX = 1;
1172                         *ZeroFlag = 1;
1173                         *CarryFlag = 0;
1174                         return true;
1175                 }
1176         } else if(PC == cmos_pc) {
1177                 // cmos
1178 #ifdef _DEBUG_LOG
1179                 emu->out_debug_log(_T("%6x\tCMOS BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
1180 #endif
1181                 if(AH == 0) {
1182                         // init cmos
1183                         memcpy(cmos, cmos_t, sizeof(cmos_t));
1184                         memcpy(cmos + CMOS_SIZE - sizeof(cmos_b), cmos_b, sizeof(cmos_b));
1185                 } else if(AH == 5) {
1186                         // get $a2
1187                         BX = cmos[0xa2] | (cmos[0xa3] << 8);
1188                 } else if(AH == 10) {
1189                         // memory to cmos
1190                         int block = AL * 10;
1191                         int len = cmos[block + 6] | (cmos[block + 7] << 8);
1192                         int dst = cmos[block + 8] | (cmos[block + 9] << 8);
1193                         int src = DS * 16 + DI;
1194                         for(int i = 0; i < len; i++) {
1195                                 cmos[dst++] = d_mem->read_data8(src++);
1196                         }
1197                 } else if(AH == 11) {
1198                         // cmos to memory
1199                         int block = AL * 10;
1200                         int len = cmos[block + 6] | (cmos[block + 7] << 8);
1201                         int src = cmos[block + 8] | (cmos[block + 9] << 8);
1202                         int dst = DS * 16 + DI;
1203                         for(int i = 0; i < len; i++) {
1204                                 d_mem->write_data8(dst++, cmos[src++]);
1205                         }
1206                 } else if(AH == 20) {
1207                         // check block header
1208                         BX = 0;
1209                 }
1210                 AH = 0;
1211                 *CarryFlag = 0;
1212                 return true;
1213         } else if(PC == wait_pc) {
1214                 // wait
1215 #ifdef _DEBUG_LOG
1216                 emu->out_debug_log(_T("%6x\tWAIT BIOS: AH=%2x,AL=%2x,CX=%4x,DX=%4x,BX=%4x,DS=%2x,DI=%2x\n"), get_cpu_pc(0), AH,AL,CX,DX,BX,DS,DI);
1217 #endif
1218                 *CarryFlag = 0;
1219                 return true;
1220         }
1221         return false;
1222 }
1223
1224 bool BIOS::bios_int_i86(int intnum, uint16 regs[], uint16 sregs[], int32* ZeroFlag, int32* CarryFlag)
1225 {
1226         uint8 *regs8 = (uint8 *)regs;
1227         
1228         if(intnum == 0x93) {
1229                 // disk bios
1230                 return bios_call_i86(0xfffc4, regs, sregs, ZeroFlag, CarryFlag);
1231         } else if(intnum == 0xaa) {
1232                 // power management bios
1233                 if(AH == 0) {
1234                         if(AL > 2) {
1235                                 AH = 2;
1236                                 *CarryFlag = 1;
1237                                 return true;
1238                         }
1239                         powmode = AL;
1240                         AH = 0;
1241                         *CarryFlag = 0;
1242                         return true;
1243                 } else if(AH == 1) {
1244                         AH = 0;
1245                         AL = BL = powmode;
1246                         *CarryFlag = 0;
1247                         return true;
1248                 }
1249         }
1250         return false;
1251 }
1252
1253 uint32 BIOS::read_signal(int ch)
1254 {
1255         // get access status
1256         uint32 stat = 0;
1257         for(int i = 0; i < MAX_DRIVE; i++) {
1258                 if(access_fdd[i]) {
1259                         stat |= 1 << i;
1260                 }
1261                 access_fdd[i] = false;
1262         }
1263         if(access_scsi) {
1264                 stat |= 0x10;
1265         }
1266         access_scsi = false;
1267         return stat;
1268 }
1269
1270 #define STATE_VERSION   2
1271
1272 void BIOS::save_state(FILEIO* state_fio)
1273 {
1274         state_fio->FputUint32(STATE_VERSION);
1275         state_fio->FputInt32(this_device_id);
1276         
1277         for(int i = 0; i < MAX_DRIVE; i++) {
1278                 disk[i]->save_state(state_fio);
1279         }
1280         state_fio->FputInt32(secnum);
1281         state_fio->FputInt32(timeout);
1282         state_fio->Fwrite(buffer, sizeof(buffer), 1);
1283         state_fio->FputUint8(powmode);
1284         state_fio->FputUint32(disk_pc1);
1285         state_fio->FputUint32(disk_pc2);
1286         state_fio->FputUint32(cmos_pc);
1287         state_fio->FputUint32(wait_pc);
1288         state_fio->FputBool(ipl_loaded);
1289 }
1290
1291 bool BIOS::load_state(FILEIO* state_fio)
1292 {
1293         if(state_fio->FgetUint32() != STATE_VERSION) {
1294                 return false;
1295         }
1296         if(state_fio->FgetInt32() != this_device_id) {
1297                 return false;
1298         }
1299         for(int i = 0; i < MAX_DRIVE; i++) {
1300                 if(!disk[i]->load_state(state_fio)) {
1301                         return false;
1302                 }
1303         }
1304         secnum = state_fio->FgetInt32();
1305         timeout = state_fio->FgetInt32();
1306         state_fio->Fread(buffer, sizeof(buffer), 1);
1307         powmode = state_fio->FgetUint8();
1308         disk_pc1 = state_fio->FgetUint32();
1309         disk_pc2 = state_fio->FgetUint32();
1310         cmos_pc = state_fio->FgetUint32();
1311         wait_pc = state_fio->FgetUint32();
1312         ipl_loaded = state_fio->FgetBool();
1313         return true;
1314 }
1315