OSDN Git Service

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