1 /***************************************************************************/
2 /* */
3 /* hard BIOS support source file */
4 /* */
5 /* This file contain support for pc engine hudson cd bios without using */
6 /* the standard routines with ports but simulating directly the function. */
7 /* */
8 /* You're welcome to help coding this piece of software, it's really */
9 /* interesting to discover precise use of each function by hacking the */
10 /* cd system and such ^^ */
11 /***************************************************************************/
12
13 #include "h6280.h"
14 #include "globals.h"
15 #include "utils.h"
16 #include "pce.h"
17
18 #undef INLINED_ACCESSORS
19
20 #if !defined(INLINED_ACCESSORS)
21
22 #define get_8bit_addr(addr) Rd6502((UInt16)(addr))
23
24 #define put_8bit_addr(addr,byte) Wr6502((addr),(byte))
25
26 #endif
27
28 /* CD related functions */
29
30 #define CD_BOOT 0x00
31 #define CD_RESET 0x01
32 #define CD_BASE 0x02
33 #define CD_READ 0x03
34 #define CD_SEEK 0x04
35 #define CD_EXEC 0x05
36 #define CD_PLAY 0x06
37 #define CD_SEARCH 0x07
38 #define CD_PAUSE 0x08
39 #define CD_STAT 0x09
40 #define CD_SUBA 0x0A
41 #define CD_DINFO 0x0B
42
43 #define CD_DINFO_NB_TRACKS 0
44 #define CD_DINFO_LENGTH 1
45 #define CD_DINFO_TRACK 2
46
47 #define CD_CONTENTS 0x0C
48 #define CD_SUBRQ 0x0D
49 #define CD_PCMRD 0x0E
50 #define CD_FADE 0x0F
51
52 /* ADPCM related functions */
53
54 #define AD_RESET 0x10
55 #define AD_TRANS 0x11
56 #define AD_READ 0x12
57 #define AD_WRITE 0x13
58 #define AD_PLAY 0x14
59 #define AD_CPLAY 0x15
60 #define AD_STOP 0x16
61 #define AD_STAT 0x17
62
63 /* BACKUP MEM related functions */
64
65 #define BM_FORMAT 0x18
66 #define BM_FREE 0x19
67 #define BM_READ 0x1A
68 #define BM_WRITE 0x1B
69 #define BM_DELETE 0x1C
70 #define BM_FILES 0x1D
71
72 /* Miscelanous functions */
73
74 #define EX_GETVER 0x1E
75 #define EX_SETVEC 0x1F
76 #define EX_GETFNT 0x20
77 #define EX_JOYSNS 0x21
78 #define EX_JOYREP 0x22
79 #define EX_SCRSIZ 0x23
80 #define EX_DOTMOD 0x24
81 #define EX_SCRMOD 0x25
82 #define EX_IMODE 0x26
83 #define EX_VMOD 0x27
84 #define EX_HMOD 0x28
85 #define EX_VSYNC 0x29
86 #define EX_RCRON 0x2A
87 #define EX_RCROFF 0x2B
88 #define EX_IRQON 0x2C
89 #define EX_IRQOFF 0x2D
90 #define EX_BGON 0x2E
91 #define EX_BGOFF 0x2F
92 #define EX_SPRON 0x30
93 #define EX_SPROFF 0x31
94 #define EX_DSPON 0x32
95 #define EX_DSPOFF 0x33
96 #define EX_DMAMOD 0x34
97 #define EX_SPRDMA 0x35
98 #define EX_SATCLR 0x36
99 #define EX_SPRPUT 0x37
100 #define EX_SETRCR 0x38
101 #define EX_SETRED 0x39
102 #define EX_SETWRT 0x3A
103 #define EX_SETDMA 0x3B
104 #define EX_BINBCD 0x3C
105 #define EX_BCDBIN 0x3D
106 #define EX_RND 0x3E
107
108 /* Math related functions */
109
110 #define MA_MUL8U 0x3F
111 #define MA_MUL8S 0x40
112 #define MA_MUL16U 0x41
113 #define MA_DIV16U 0x42
114 #define MA_DIV16S 0x43
115 #define MA_SQRT 0x44
116 #define MA_SIN 0x45
117 #define MA_COS 0x46
118 #define MA_ATNI 0x47
119
120 /* PSG BIOS functions */
121
122 #define PSG_BIOS 0x48
123 #define GRP_BIOS 0x49
124 #define KEY_BIOS 0x4A
125 #define PSG_DRIVE 0x4B
126 #define EX_COLORC 0x4C
127
128
129 #define MA_MUL16S 0x4F
130 #define MA_CBASIS 0x50
131
132 #define _al 0xF8
133 #define _ah 0xF9
134 #define _bl 0xFA
135 #define _bh 0xFB
136 #define _cl 0xFC
137 #define _ch 0xFD
138 #define _dl 0xFE
139 #define _dh 0xFF
140
141 #define _ax 0xF8
142 #define _bx 0xFA
143 #define _cx 0xFC
144 #define _dx 0xFE
145
146
147 int testadpcm = 0;
148
149 #ifdef CD_DEBUG
150
cdbios_functions(int index)151 const char *cdbios_functions(int index)
152 {
153 switch(index) {
154 case CD_BOOT:
155 return "CD_BOOT";
156 case CD_RESET:
157 return "CD_RESET";
158 case CD_BASE:
159 return "CD_BASE";
160 case CD_READ:
161 return "CD_READ";
162 case CD_SEEK:
163 return "CD_SEEK";
164 case CD_EXEC:
165 return "CD_EXEC";
166 case CD_PLAY:
167 return "CD_PLAY";
168 case CD_SEARCH:
169 return "CD_SEARCH";
170 case CD_PAUSE:
171 return "CD_PAUSE";
172 case CD_STAT:
173 return "CD_STAT";
174 case CD_SUBA:
175 return "CD_SUBA";
176 case CD_DINFO:
177 return "CD_DINFO";
178 case CD_CONTENTS:
179 return "CD_CONTENTS";
180 case CD_SUBRQ:
181 return "CD_SUBRQ";
182 case CD_PCMRD:
183 return "CD_PCMRD";
184 case CD_FADE:
185 return "CD_FADE";
186
187 case AD_RESET:
188 return "AD_RESET";
189 case AD_TRANS:
190 return "AD_TRANS";
191 case AD_READ:
192 return "AD_READ";
193 case AD_WRITE:
194 return "AD_WRITE";
195 case AD_PLAY:
196 return "AD_PLAY";
197 case AD_CPLAY:
198 return "AD_CPLAY";
199 case AD_STOP:
200 return "AD_STOP";
201 case AD_STAT:
202 return "AD_STAT";
203
204 case BM_FORMAT:
205 return "BM_FORMAT";
206 case BM_FREE:
207 return "BM_FREE";
208 case BM_READ:
209 return "BM_READ";
210 case BM_WRITE:
211 return "BM_WRITE";
212 case BM_DELETE:
213 return "BM_DELETE";
214 case BM_FILES:
215 return "BM_FILES";
216
217 case EX_GETVER:
218 return "EX_GETVER";
219 case EX_SETVEC:
220 return "EX_SETVEC";
221 case EX_GETFNT:
222 return "EX_GETFNT";
223 case EX_JOYSNS:
224 return "EX_JOYSNS";
225 case EX_JOYREP:
226 return "EX_JOYREP";
227
228 case EX_SCRSIZ:
229 return "EX_SCRSIZ";
230 case EX_DOTMOD:
231 return "EX_DOTMOD";
232 case EX_SCRMOD:
233 return "EX_SCRMOD";
234 case EX_IMODE:
235 return "EX_IMODE";
236 case EX_VMOD:
237 return "EX_VMOD";
238 case EX_HMOD:
239 return "EX_HMOD";
240 case EX_VSYNC:
241 return "EX_VSYNC";
242 case EX_RCRON:
243 return "EX_RCRON";
244 case EX_RCROFF:
245 return "EX_RCROFF";
246 case EX_IRQON:
247 return "EX_IRQON";
248 case EX_IRQOFF:
249 return "EX_IRQOFF";
250 case EX_BGON:
251 return "EX_BGON";
252 case EX_BGOFF:
253 return "EX_BGOFF";
254 case EX_SPRON:
255 return "EX_SPRON";
256 case EX_SPROFF:
257 return "EX_SPROFF";
258 case EX_DSPON:
259 return "EX_DSPON";
260 case EX_DSPOFF:
261 return "EX_DSPOFF";
262 case EX_DMAMOD:
263 return "EX_DMAMOD";
264 case EX_SPRDMA:
265 return "EX_SPRDMA";
266 case EX_SATCLR:
267 return "EX_SATCLR";
268 case EX_SPRPUT:
269 return "EX_SPRPUT";
270 case EX_SETRCR:
271 return "EX_SETRCR";
272 case EX_SETRED:
273 return "EX_SETRED";
274 case EX_SETWRT:
275 return "EX_SETWRT";
276 case EX_SETDMA:
277 return "EX_SETDMA";
278 case EX_BINBCD:
279 return "EX_BINBCD";
280 case EX_BCDBIN:
281 return "EX_BCDBIN";
282 case EX_RND:
283 return "EX_RND";
284
285 case MA_MUL8U:
286 return "MA_MUL8U";
287 case MA_MUL8S:
288 return "MA_MUL8S";
289 case MA_MUL16U:
290 return "MA_MUL16U";
291 case MA_DIV16S:
292 return "MA_DIV16S";
293 case MA_DIV16U:
294 return "MA_DIV16U";
295 case MA_SQRT:
296 return "MA_SQRT";
297 case MA_SIN:
298 return "MA_SIN";
299 case MA_COS:
300 return "MA_COS";
301 case MA_ATNI:
302 return "MA_ATNI";
303
304 case PSG_BIOS:
305 return "PSG_BIOS";
306
307 case GRP_BIOS:
308 return "GRP_BIOS";
309 case KEY_BIOS:
310 return "KEY_BIOS";
311 case PSG_DRIVE:
312 return "PSG_DRIVE";
313 case EX_COLORC:
314 return "EX_COLORC";
315
316 default:
317 break;
318 }
319
320 return "?UNKNOWN?";
321 }
322
323 #endif
324
325
handle_bios(void)326 void handle_bios(void)
327 {
328 #ifdef CD_DEBUG
329 static int last_op = -1, last_ax = -1, last_bx = -1, last_cx = -1, last_dx = -1;
330 int this_op = imm_operand(reg_pc + 1), this_ax = get_16bit_zp(_ax), this_bx = get_16bit_zp(_bx),
331 this_cx = get_16bit_zp(_cx), this_dx = get_16bit_zp(_dx);
332
333 /*
334 * Skip over polling functions to avoid the spam
335 */
336 if ((this_op != CD_PCMRD) && (this_op != CD_SUBA) && (this_op != EX_JOYSNS) && (this_op != AD_STAT)) {
337 if ((last_op != this_op) || (last_ax != this_ax) || (last_bx != this_bx) || (last_cx != this_cx) ||
338 (last_dx != this_dx)) {
339 fprintf(stderr, "\n%s: ax=%d ah=%d al=%d bx=%d bh=%d bl=%d\ncx=%d ch=%d cl=%d dx=%d dh=%d dl=%d",
340 cdbios_functions(imm_operand(reg_pc + 1)), get_16bit_zp(_ax), get_8bit_zp(_ah), get_8bit_zp(_al),
341 get_16bit_zp(_bx), get_8bit_zp(_bh), get_8bit_zp(_bl),
342 get_16bit_zp(_cx), get_8bit_zp(_ch), get_8bit_zp(_cl),
343 get_16bit_zp(_dx), get_8bit_zp(_dh), get_8bit_zp(_dl));
344 last_op = this_op;
345 last_ax = this_ax;
346 last_bx = this_bx;
347 last_cx = this_cx;
348 last_dx = this_dx;
349 } else {
350 fprintf(stderr, ".");
351 }
352 }
353 #endif
354
355 switch(imm_operand((UInt16)(reg_pc + 1))) {
356 case CD_RESET:
357 switch(CD_emulation) {
358 case 1: /* true CD */
359 if (osd_cd_init(ISO_filename) != 0) {
360 Log("CD rom drive init error!\n");
361 exit(4);
362 }
363 break;
364 case 2: /* ISO */
365 case 3: /* ISQ */
366 case 4: /* BIN */
367 fill_cd_info();
368 break;
369 /* HCD : nothing to be done */
370 }
371
372 put_8bit_addr(0x222D, 1);
373 // This byte is set to 1 if a disc if present
374
375 rts();
376 break;
377
378 case CD_READ:
379 {
380 UChar mode = get_8bit_zp(_dh);
381 UInt32 nb_to_read = get_8bit_zp(_al);
382 UInt16 offset = get_16bit_zp(_bx);
383
384 pce_cd_sectoraddy = (get_8bit_zp(_cl) << 16) +
385 (get_8bit_zp(_ch) << 8) +
386 (get_8bit_zp(_dl));
387
388 pce_cd_sectoraddy += (get_8bit_addr(0x2274 + 3 * get_8bit_addr(0x2273)) << 16) +
389 (get_8bit_addr(0x2275 + 3 * get_8bit_addr(0x2273)) << 8) +
390 (get_8bit_addr(0x2276 + 3 * get_8bit_addr(0x2273)));
391
392 switch(mode) {
393
394 case 0: // local, size in byte
395 nb_to_read = get_16bit_zp(_ax);
396
397 while (nb_to_read >= 2048) {
398 int index;
399
400 pce_cd_read_sector();
401 for (index = 0;index < 2048; index++)
402 put_8bit_addr(offset++, cd_read_buffer[index]);
403 nb_to_read -= 2048;
404 }
405
406 if (nb_to_read) {
407 UInt32 index;
408
409 pce_cd_read_sector();
410 for (index = 0; index < nb_to_read; index++)
411 put_8bit_addr(offset++, cd_read_buffer[index]);
412 }
413
414 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
415
416 cd_sectorcnt = 0;
417 cd_read_buffer = NULL;
418 pce_cd_read_datacnt = 0;
419
420 rts();
421 break;
422
423
424 case 1: // local, size in sector
425 while (nb_to_read) {
426 int index;
427
428 pce_cd_read_sector();
429 for (index = 0; index < 2048; index++)
430 put_8bit_addr(offset++, cd_read_buffer[index]);
431 nb_to_read--;
432 }
433 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
434
435 // TEST
436 io.cd_port_1800 |= 0xD0;
437 // TEST
438
439 cd_sectorcnt = 0;
440 cd_read_buffer = NULL;
441 pce_cd_read_datacnt = 0;
442
443 rts();
444 break;
445
446 case 2:
447 case 3:
448 case 4:
449 case 5:
450 case 6:
451 {
452 UChar nb_bank_to_fill_completely = nb_to_read >> 2;
453 UChar remaining_block_to_write = nb_to_read & 3;
454 UChar bank_where_to_write = get_8bit_zp(_bl);
455 UInt16 offset_in_bank = 0;
456
457 while (nb_bank_to_fill_completely--) {
458 pce_cd_read_sector();
459 memcpy(ROMMapW[bank_where_to_write], cd_read_buffer, 2048);
460
461 pce_cd_read_sector();
462 memcpy(ROMMapW[bank_where_to_write] + 2048, cd_read_buffer, 2048);
463
464 pce_cd_read_sector();
465 memcpy(ROMMapW[bank_where_to_write] + 2048 * 2, cd_read_buffer, 2048);
466
467 pce_cd_read_sector();
468 memcpy(ROMMapW[bank_where_to_write] + 2048 * 3, cd_read_buffer, 2048);
469
470 bank_where_to_write++;
471 }
472
473 offset_in_bank = 0;
474 while (remaining_block_to_write--) {
475 pce_cd_read_sector();
476 #ifndef FINAL_RELEASE
477 fprintf(stderr, "Writing quarter to ROMMap[0x%x] + 0x%x\n\n",
478 bank_where_to_write,offset_in_bank);
479 #endif
480 memcpy(ROMMapW[bank_where_to_write] + offset_in_bank, cd_read_buffer, 2048);
481 offset_in_bank += 2048;
482 }
483 }
484
485 cd_sectorcnt = 0;
486 cd_read_buffer = NULL;
487 pce_cd_read_datacnt = 0;
488
489 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
490 rts();
491 break;
492
493 case 0xFE:
494 IO_write(0, 0);
495 IO_write(2, (UChar)(offset & 0xFF));
496 IO_write(3, (UChar)(offset >> 8));
497 IO_write(0, 2);
498 {
499 UInt32 nb_sector;
500 nb_to_read = get_16bit_zp(_ax);
501 nb_sector = (nb_to_read >> 11) + ((nb_to_read & 2047) ? 1 : 0);
502
503 while (nb_sector) {
504 int x, index = min(2048, (int)nb_to_read);
505
506 pce_cd_read_sector();
507
508 //memcpy(&VRAM[offset],cd_read_buffer,index);
509 for (x = 0; x < index; x += 2) {
510 IO_write(2, cd_read_buffer[x]);
511 IO_write(3, cd_read_buffer[x + 1]);
512 }
513
514 nb_to_read-=index;
515 nb_sector--;
516 }
517
518 cd_sectorcnt = 0;
519 cd_read_buffer = NULL;
520 pce_cd_read_datacnt = 0;
521
522 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
523 rts();
524 // break;
525 }
526 break;
527
528 case 0xFF:
529 if (!nb_to_read)
530 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0x22]);
531 else {
532 IO_write(0, 0);
533 IO_write(2, (UChar)(offset & 0xFF));
534 IO_write(3, (UChar)(offset >> 8));
535 IO_write(0, 2);
536
537 while (nb_to_read) {
538 int index;
539
540 pce_cd_read_sector();
541
542 for (index = 0; index < 2048; index += 2) {
543 IO_write(2, cd_read_buffer[index]);
544 IO_write(3, cd_read_buffer[index + 1]);
545 }
546
547 nb_to_read--;
548 }
549
550 cd_sectorcnt = 0;
551 cd_read_buffer = NULL;
552 pce_cd_read_datacnt = 0;
553
554 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
555 }
556 rts();
557 break;
558
559 default :
560 /* the reading mode isn't supported and we simulate the
561 * behaviour of the 2 first byte opcode and keep going
562 * thus hooking further calls to this function
563 */
564 put_8bit_addr(0x2273, 0);
565 reg_pc += 2;
566 #ifdef CD_DEBUG
567 fprintf(stderr, "Reading mode not supported : %d\n_AX=0x%04x\n_BX=0x%04x\n_CX=0x%04x\n_DX=0x%04x\n",
568 mode, get_16bit_zp(_ax), get_16bit_zp(_bx), get_16bit_zp(_cx), get_16bit_zp(_dx));
569 #endif
570 }
571 }
572 break;
573
574 case CD_PAUSE:
575 switch(CD_emulation) {
576 case 1:
577 osd_cd_pause();
578 break;
579 case 2:
580 case 3:
581 case 4:
582 break;
583 case 5:
584 HCD_pause_playing();
585 break;
586 }
587 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
588 rts();
589 break;
590
591 case CD_STAT:
592 {
593 /* TODO : makes this function work for cd and hcd at least
594 * gives info on the status of playing music
595 */
596 int retval;
597
598 osd_cd_status(&retval);
599
600 reg_p = ((reg_p & (~(FL_N | FL_T | FL_Z))) | flnz_list[reg_a = 0]);
601 }
602 rts();
603 break;
604
605 case CD_SUBA:
606 /* TODO : check the real functionality of this function
607 * seems to fill a whole buffer of 10 bytes but
608 * meaning of this array is mostly unknown
609 */
610 {
611 UInt16 offset = get_16bit_zp(_bx);
612 // static UChar result = 3;
613
614 // result = 3 - result;
615
616 // Wr6502(offset, result); // TEST, for golden axe (3) and solid force (0)
617 osd_cd_subchannel_info(offset);
618 }
619
620 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
621 rts();
622 break;
623
624 case CD_PCMRD:
625 // do almost nothing
626 // fake the audio player, maybe not other piece of code
627 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = get_8bit_zp(0x41)]);
628 rts();
629 break;
630
631 case CD_SEARCH:
632 /* unsure how this operates
633 * needed for playing audio discs with a system card
634 *
635 * _al contains the track we're "searching" for.
636 * If I'm not mistaken _bh is a flag with that 7th bit (128) set
637 * for SEEK_SET type behaviour, while if the 2nd bit (2) is set
638 * we play the track after searching for it.
639 */
640 {
641 // if (get_8bit_zp(_bh) & 0x02) {
642 // osd_cd_play_audio_track(bcdbin[get_8bit_zp(_al)]);
643 // } else {
644 /* UInt16 bufaddr = get_16bit_zp(_bx); */
645 int min, sec, fra, con;
646
647 osd_cd_stop_audio();
648
649 osd_cd_track_info(bcdbin[get_8bit_zp(_al)], &min, &sec, &fra, &con);
650
651 /*
652 put_8bit_addr(bufaddr, min);
653 put_8bit_addr(bufaddr + 1, sec);
654 put_8bit_addr(bufaddr + 2, fra);
655 put_8bit_addr(bufaddr + 3, con);
656 */
657
658 if (get_8bit_zp(_bh) & 0x02)
659 osd_cd_play_audio_track(bcdbin[get_8bit_zp(_al)]);
660 // else
661 // osd_cd_stop_audio();
662 }
663 reg_p = ((reg_p & (~(FL_N | FL_T | FL_Z))) | flnz_list[reg_a = 0]);
664 rts();
665 break;
666
667 case AD_RESET:
668 // do nothing
669 // don't return any value
670 // reg_p = ((reg_p & (~(FL_N | FL_T | FL_Z))) | flnz_list[reg_a = 0]);
671 rts();
672 break;
673
674 case AD_TRANS:
675 {
676 UInt32 nb_to_read = get_8bit_zp(_al);
677 UInt16 ADPCM_offset = get_16bit_zp(_bx);
678
679 pce_cd_sectoraddy = (get_8bit_zp(_cl) << 16) +
680 (get_8bit_zp(_ch) << 8) +
681 (get_8bit_zp(_dl));
682
683 pce_cd_sectoraddy += (get_8bit_addr(0x2274 + 3 * get_8bit_addr(0x2273)) << 16) +
684 (get_8bit_addr(0x2275 + 3 * get_8bit_addr(0x2273)) << 8) +
685 (get_8bit_addr(0x2276 + 3 * get_8bit_addr(0x2273)));
686
687 if (!get_8bit_zp(_dh))
688 io.adpcm_dmaptr = ADPCM_offset;
689 else
690 ADPCM_offset = io.adpcm_dmaptr;
691
692 while (nb_to_read) {
693 pce_cd_read_sector();
694 memcpy(PCM + ADPCM_offset, cd_read_buffer, 2048);
695 ADPCM_offset += 2048;
696 nb_to_read--;
697 }
698
699 io.adpcm_dmaptr = ADPCM_offset;
700
701 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
702 }
703 rts();
704 break;
705
706 case AD_READ:
707 {
708 UInt16 ADPCM_buffer = get_16bit_zp(_cx);
709 UChar type = get_8bit_zp(_dh);
710 UInt16 address = get_16bit_zp(_bx);
711 UInt16 size = get_16bit_zp(_ax);
712
713 switch(type) {
714 case 0: // memory write
715 io.adpcm_rptr = ADPCM_buffer;
716 while (size) {
717 put_8bit_addr(address++, PCM[io.adpcm_rptr++]);
718 size--;
719 }
720 break;
721 case 0xFF: // VRAM write
722 io.adpcm_rptr = ADPCM_buffer;
723
724 IO_write(0, 0);
725 IO_write(2, (UChar)(address & 0xFF));
726 IO_write(3, (UChar)(address >> 8));
727
728 IO_write(0, 2);
729
730 while (size) {
731 IO_write(2, PCM[io.adpcm_rptr++]);
732 size--;
733
734 if (size) {
735 IO_write(3, PCM[io.adpcm_rptr++]);
736 size--;
737 }
738 }
739 break;
740 case 2:
741 case 3:
742 case 4:
743 case 5:
744 case 6:
745 {
746 UChar bank_to_fill = get_8bit_zp(_bl);
747 UInt32 i;
748
749 while (size >= 2048) {
750 for (i = 0; i < 2048; i++)
751 ROMMapW[bank_to_fill][i] = PCM[io.adpcm_rptr++];
752
753 bank_to_fill++;
754
755 size -= 2048;
756 }
757
758 for (i = 0; i < size; i++)
759 ROMMapW[bank_to_fill][i] = PCM[io.adpcm_rptr++];
760
761 }
762 break;
763 default:
764 Log("Type reading not supported in AD_READ : %x\n", type);
765 exit(-2);
766 }
767 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
768 rts();
769 }
770 break;
771
772 case AD_PLAY:
773 io.adpcm_pptr = get_16bit_zp(_bx) << 1;
774
775 io.adpcm_psize = get_16bit_zp(_ax) << 1;
776
777 io.adpcm_rate = (UChar)(32 / (16 - (get_8bit_zp(_dh) & 15)));
778
779 new_adpcm_play = 1;
780
781 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
782 rts();
783 break;
784
785 case AD_STOP:
786 AdpcmFilledBuf = new_adpcm_play = 0;
787 rts();
788 break;
789
790 case AD_STAT:
791 {
792
793 if (AdpcmFilledBuf > (io.adpcm_psize / 2))
794 reg_x = 4;
795 else if (AdpcmFilledBuf == 0)
796 reg_x = 1;
797 else
798 reg_x = 0;
799
800 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = (UChar)(reg_x == 1 ? 0 : 1)]);
801 }
802 rts();
803 break;
804
805 case CD_DINFO:
806 switch(get_8bit_zp(_al)) {
807 case CD_DINFO_TRACK:
808 {
809 UInt16 buf_offset = get_16bit_zp(_bx);
810 // usually 0x2256 in system 3.0
811 // _ah contain the number of the track
812
813 switch(CD_emulation) {
814 case 2:
815 case 3:
816 case 4:
817 case 5:
818 put_8bit_addr( (UInt16)buf_offset, CD_track[bcdbin[get_8bit_zp(_ah)]].beg_min);
819 put_8bit_addr( (UInt16)(buf_offset + 1), CD_track[bcdbin[get_8bit_zp(_ah)]].beg_sec);
820 put_8bit_addr( (UInt16)(buf_offset + 2), CD_track[bcdbin[get_8bit_zp(_ah)]].beg_fra);
821 put_8bit_addr( (UInt16)(buf_offset + 3), CD_track[bcdbin[get_8bit_zp(_ah)]].type);
822 break;
823 case 1:
824 {
825 int Min, Sec, Fra, Ctrl;
826
827 osd_cd_track_info(bcdbin[get_8bit_zp(_ah)], &Min, &Sec, &Fra, &Ctrl);
828
829 put_8bit_addr( (UInt16)(buf_offset), binbcd[Min]);
830 put_8bit_addr( (UInt16)(buf_offset + 1), binbcd[Sec]);
831 put_8bit_addr( (UInt16)(buf_offset + 2), binbcd[Fra]);
832 put_8bit_addr( (UInt16)(buf_offset + 3), (UChar)Ctrl);
833
834 }
835 break;
836 }
837 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
838 }
839 rts();
840 break;
841
842 case CD_DINFO_NB_TRACKS:
843 {
844 UInt16 buf_offset = get_16bit_zp(_bx);
845
846 switch(CD_emulation) {
847 case 2:
848 case 3:
849 case 4:
850 put_8bit_addr( (UInt16)(buf_offset), binbcd[01]); // Number of first track (BCD)
851 put_8bit_addr( (UInt16)(buf_offset + 1), binbcd[nb_max_track]); // Number of last track (BCD)
852 break;
853 case 1:
854 {
855 int first_track, last_track;
856
857 osd_cd_nb_tracks(&first_track, &last_track);
858
859 put_8bit_addr( (UInt16)(buf_offset), binbcd[first_track]);
860 put_8bit_addr( (UInt16)(buf_offset + 1), binbcd[last_track]);
861 }
862 break;
863 case 5:
864 put_8bit_addr( (UInt16)(buf_offset), binbcd[HCD_first_track]);
865 put_8bit_addr( (UInt16)(buf_offset + 1), binbcd[HCD_last_track]);
866 break;
867 }
868 }
869 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
870 rts();
871 break;
872
873 case CD_DINFO_LENGTH:
874 {
875 UInt16 buf_offset = get_16bit_zp(_bx);
876 int min, sec, frame;
877
878 osd_cd_length(&min, &sec, &frame);
879
880 put_8bit_addr( (UInt16)(buf_offset), binbcd[min]);
881 put_8bit_addr( (UInt16)(buf_offset + 1), binbcd[sec]);
882 put_8bit_addr( (UInt16)(buf_offset + 2), binbcd[frame]);
883
884 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
885 }
886 rts();
887 break;
888
889 default:
890 Log("bios.c: Sub function 0X%02X from CD_DINFO not handled\n", get_8bit_zp(_al));
891 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 1]);
892 rts();
893 break;
894 }
895 break;
896
897 case CD_PLAY:
898
899 if (get_8bit_zp(_bh) == 0x80) {
900 int status;
901
902 // playing a whole track
903
904 switch(CD_emulation) {
905 case 1:
906 osd_cd_status(&status);
907
908 if (status == CDROM_AUDIO_PAUSED)
909 osd_cd_resume();
910 else if (status == CDROM_AUDIO_PLAY)
911 osd_cd_stop_audio();
912
913 osd_cd_play_audio_track(bcdbin[get_8bit_zp(_al)]);
914 break;
915
916 case 2:
917 case 3:
918 case 4:
919 // ignoring cd playing
920 break;
921 case 5:
922 HCD_play_track(bcdbin[get_8bit_zp(_al)], (char)(get_8bit_zp(_dh) & 1) );
923 break;
924 }
925 } else if (get_8bit_zp(_bh) == 192) { /* resume from pause if paused */
926 int status;
927
928 osd_cd_status(&status);
929
930 if (status == CDROM_AUDIO_PAUSED)
931 osd_cd_resume();
932 else
933 osd_cd_play_audio_track(bcdbin[get_8bit_zp(_al)]);
934
935 } else {
936 int status;
937
938 int min1 = bcdbin[get_8bit_zp(_al)];
939 int sec1 = bcdbin[get_8bit_zp(_ah)];
940 int fra1 = bcdbin[get_8bit_zp(_bl)];
941
942 int min2 = bcdbin[get_8bit_zp(_cl)];
943 int sec2 = bcdbin[get_8bit_zp(_ch)];
944 int fra2 = bcdbin[get_8bit_zp(_dl)];
945
946 switch(CD_emulation) {
947 case 1:
948 osd_cd_status(&status);
949 if ((status == CDROM_AUDIO_PLAY) || (status == CDROM_AUDIO_PAUSED))
950 osd_cd_stop_audio();
951 osd_cd_play_audio_range((UChar)min1, (UChar)sec1, (UChar)fra1, (UChar)min2, (UChar)sec2, (UChar)fra2);
952 break;
953 case 2:
954 case 3:
955 case 4:
956 // ignoring cd playing
957 break;
958 case 5:
959 // HCD_play_sectors(begin_sect, sect_len, get_8bit_zp(_dh) & 1);
960 break;
961 }
962 }
963 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
964 rts();
965 break;
966
967 case EX_JOYSNS:
968 {
969 UChar dummy[5], index;
970
971 for (index = 0; index < 5; index++) {
972 dummy[index] = get_8bit_addr(0x2228 + index);
973 put_8bit_addr( (UInt16)(0x2232 + index), dummy[index]);
974 put_8bit_addr( (UInt16)(0x2228 + index), io.JOY[index]);
975 put_8bit_addr( (UInt16)(0x222D + index), (io.JOY[index] ^ dummy[index]) & io.JOY[index]);
976 }
977 }
978 /* TODO : check if A <- 0 is needed here */
979 rts();
980 break;
981
982 case BM_FREE:
983 {
984 SInt16 free_mem;
985
986 free_mem = (SInt16)(WRAM[4] + (WRAM[5] << 8));
987 free_mem -= WRAM[6] + (WRAM[7] << 8);
988 free_mem -= 0x12; /* maybe the header */
989
990 if (free_mem < 0)
991 free_mem = 0;
992
993 put_8bit_zp(_cl, (UChar)(free_mem & 0xFF));
994 put_8bit_zp(_ch, (UChar)(free_mem >> 8));
995
996 reg_p = ((reg_p & (~(FL_N|FL_T|FL_Z))) | flnz_list[reg_a = 0]);
997 rts();
998 break;
999 }
1000
1001 #ifdef CD_DEBUG
1002 case MA_MUL8U:
1003 {
1004 UInt16 res;
1005
1006 res = get_8bit_zp(_ax) * get_8bit_zp(_bx);
1007
1008 put_8bit_zp(_cl, res & 0xFF);
1009 put_8bit_zp(_ch, res >> 8);
1010
1011 rts();
1012 break;
1013 }
1014
1015 case MA_MUL8S:
1016 {
1017 SInt16 res;
1018
1019 res = get_8bit_zp(_ax) * get_8bit_zp(_bx);
1020
1021 put_8bit_zp(_cl, res & 0xFF);
1022 put_8bit_zp(_ch, res >> 8);
1023
1024 rts();
1025 break;
1026 }
1027
1028 case MA_MUL16U:
1029 {
1030 UInt32 res;
1031
1032 res = get_16bit_zp(_ax) * get_16bit_zp(_bx);
1033
1034 put_8bit_zp(_cl, res & 0xFF);
1035 put_8bit_zp(_ch, (res >> 8) & 0xFF);
1036 put_8bit_zp(_dl, (res >> 16) & 0xFF);
1037 put_8bit_zp(_dh, (res >> 24) & 0xFF);
1038
1039 rts();
1040 break;
1041 }
1042
1043 case MA_DIV16U:
1044 {
1045 UInt16 res, rem;
1046
1047 res = get_16bit_zp(_ax) / get_16bit_zp(_bx);
1048 rem = get_16bit_zp(_ax) % get_16bit_zp(_bx);
1049
1050 put_8bit_zp(_cl, res & 0xFF);
1051 put_8bit_zp(_ch, res >> 8);
1052 put_8bit_zp(_dl, rem & 0xFF);
1053 put_8bit_zp(_dh, res >> 8);
1054
1055 rts();
1056 break;
1057 }
1058
1059 case MA_DIV16S:
1060 {
1061 SInt16 res, rem;
1062
1063 res = get_16bit_zp(_ax) / get_16bit_zp(_bx);
1064 rem = get_16bit_zp(_ax) % get_16bit_zp(_bx);
1065
1066 put_8bit_zp(_cl, res & 0xFF);
1067 put_8bit_zp(_ch, res >> 8);
1068 put_8bit_zp(_dl, rem & 0xFF);
1069 put_8bit_zp(_dh, rem >> 8);
1070
1071 rts();
1072 break;
1073 }
1074
1075 case MA_MUL16S:
1076 {
1077 SInt32 res;
1078
1079 res = get_16bit_zp(_ax) * get_16bit_zp(_bx);
1080
1081 put_8bit_zp(_cl, res & 0xFF);
1082 put_8bit_zp(_ch, (res >> 8) & 0xFF);
1083 put_8bit_zp(_dl, (res >> 16) & 0xFF);
1084 put_8bit_zp(_dh, (res >> 24) & 0xFF);
1085
1086 rts();
1087 break;
1088 }
1089 #endif
1090
1091 default:
1092 /* unhandled function, restoring initial behaviour */
1093 put_8bit_addr( (UInt16)(reg_pc), CDBIOS_replace[imm_operand( (UInt16)(reg_pc + 1))][0]);
1094 put_8bit_addr( (UInt16)(reg_pc + 1), CDBIOS_replace[imm_operand( (UInt16)(reg_pc + 1))][1]);
1095 }
1096 }
1097