5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups by James L. Hammons
9 // 02/20/2002: Fixed sector to MSF conversion
10 // 02/19/2002: Fixed a bug in TOC encoding function
15 /* Added by SDLEMU (http://sdlemu.ngemu.com */
16 /* Some GCC UNIX includes */
21 #define ERR_FLAG 0x3e00
23 #define BIOS_VER 0x3004
26 #define CDBIOS_INITM 1
27 #define CDBIOS_INITF 2
29 #define CD_INIT 0x3000
30 #define CD_MODE 0x3006
32 #define CD_JERI 0x3012
33 #define CD_SPIN 0x3018
34 #define CD_STOP 0x301E
35 #define CD_MUTE 0x3024
36 #define CD_UMUTE 0x302A
37 #define CD_PAUSE 0x3030
38 #define CD_UPAUSE 0x3036
39 #define CD_READ 0x303C
40 #define CD_UREAD 0x3042
41 #define CD_SETUP 0x3048
43 #define CD_OSAMP 0x3054
44 #define CD_GETTOC 0x306A
45 #define CD_INITM 0x3060
46 #define CD_INITF 0x3066
48 char * cdbios_command[] =
49 { "init", "mode", "ack", "jeri", "spin", "stop", "mute", "umute", "pause", "upause",
50 "read", "uread", "setup", "ptr", "osamp", "getoc", "initm", "initf",
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
53 #define CDROM_AUDIO_MODE 0
54 #define CDROM_DATA_MODE 1
56 #define CDROM_SINGLE_SPEED 0
57 #define CDROM_DOUBLE_SPEED 1
59 #define CDROM_STATUS_OK 0
60 #define CDROM_STATUS_ERROR 1
62 uint32 cdrom_mode = CDROM_DATA_MODE;
63 uint32 cdrom_speed = CDROM_SINGLE_SPEED;
64 uint32 cdrom_oversample_factor = 1;
65 uint32 cdbios_session = 0;
67 uint32 cdrom_destination_buffer_beginning;
68 uint32 cdrom_destination_buffer_end;
69 uint32 cdrom_time_code;
70 uint32 cdrom_seek_only;
71 uint32 cdrom_partition_marker;
72 uint32 cdrom_circular_buffer_size;
74 uint32 cdbios_init_type;
75 uint32 * cdbios_sector_lut;
76 uint32 cdbios_init_done = 0;
79 void cdbios_build_sector_lut(void)
85 s_cdi_track *last_track=&cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].tracks[cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].nb_of_tracks-1];
87 last_sector=last_track->start_lba+last_track->total_length-1;
90 cdbios_sector_lut=(uint32*)malloc((last_sector+1)*sizeof(uint32));
91 memset(cdbios_sector_lut,0xff,(last_sector+1)*sizeof(uint32));
93 for (int session=0;session<cdi_descriptor->nb_of_sessions;session++)
95 for (int track=0;track<cdi_descriptor->sessions[session].nb_of_tracks;track++)
97 s_cdi_track *current_track=&cdi_descriptor->sessions[session].tracks[track];
99 if (offset<((int32)(current_track->start_lba-1)))
101 fprintf(log_get(),"cdbios: postgap between %i and %i\n",offset,current_track->start_lba-1);
104 for (;offset<current_track->start_lba;offset++)
106 cdbios_sector_lut[offset]=0xffffffff;
110 fprintf(log_get(),"cdbios: data between %i and %i\n",offset,current_track->start_lba+current_track->total_length-1);
111 for (;offset<current_track->start_lba+current_track->total_length;offset++)
113 cdbios_sector_lut[offset]=sector;
122 void cdbios_get_time(uint32 sectors, uint32 *mm, uint32 *ss, uint32 *ff)
124 uint32 _sectors=sectors;
126 uint32 _mm=(sectors/(60*75));
127 sectors-=(_mm*(60*75));
128 uint32 _ss=(sectors/75);
137 // fprintf(log_get(),"[%.2i:%.2i:%.2i]\n",_mm,_ss,_ff);
140 void cdbios_encode_toc(void)
145 JaguarWriteByte(base++,0x00);
146 JaguarWriteByte(base++,0x00);
147 JaguarWriteByte(base++,0x01);
150 for (i=0;i<cdi_descriptor->nb_of_sessions;i++)
151 nbtracks+=cdi_descriptor->sessions[i].nb_of_tracks;
153 JaguarWriteByte(base++,nbtracks+1);
154 JaguarWriteByte(base++,cdi_descriptor->nb_of_sessions);
160 cdbios_get_time(cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].tracks[cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].nb_of_tracks-1].start_lba+
161 cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].tracks[cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].nb_of_tracks-1].length+
162 cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].tracks[cdi_descriptor->sessions[cdi_descriptor->nb_of_sessions-1].nb_of_tracks-1].pregap_length,
165 JaguarWriteByte(base++,mm);
166 JaguarWriteByte(base++,ss);
167 JaguarWriteByte(base++,ff);
170 for (i=0;i<cdi_descriptor->nb_of_sessions;i++)
171 for (int j=0;j<cdi_descriptor->sessions[i].nb_of_tracks;j++)
173 s_cdi_track *track=&cdi_descriptor->sessions[i].tracks[j];
175 // fprintf(log_get(),"track %i\n",track_count);
177 JaguarWriteByte(base++,track_count);
178 cdbios_get_time(track->start_lba+track->pregap_length,&mm,&ss,&ff);
179 JaguarWriteByte(base++,mm);
180 JaguarWriteByte(base++,ss);
181 JaguarWriteByte(base++,ff);
182 JaguarWriteByte(base++,i);
183 cdbios_get_time(track->length,&mm,&ss,&ff);
184 JaguarWriteByte(base++,mm);
185 JaguarWriteByte(base++,ss);
186 JaguarWriteByte(base++,ff);
191 cdi_tracks_count=track_count;
192 cdi_tracks=(s_cdi_track**)malloc(track_count*sizeof(s_cdi_track*));
194 for (i=0;i<cdi_descriptor->nb_of_sessions;i++)
196 for (int j=0;j<cdi_descriptor->sessions[i].nb_of_tracks;j++)
198 cdi_tracks[track_count]=&cdi_descriptor->sessions[i].tracks[j];
204 void cdbios_decode_toc(void)
209 fprintf(log_get(),"cdbios: toc:\n");
210 fprintf(log_get(),"cdbios:\n");
212 fprintf(log_get(),"cdbios: minimum track number: %i\n",JaguarReadByte(addr++));
213 fprintf(log_get(),"cdbios: maximum track number: %i\n",nb_tracks=JaguarReadByte(addr++));
214 fprintf(log_get(),"cdbios: number of sessions : %i\n",JaguarReadByte(addr++));
215 fprintf(log_get(),"cdbios: start of last lead out time: %.2i:%.2i:%.2i\n",
216 JaguarReadByte(addr++),JaguarReadByte(addr++),JaguarReadByte(addr++));
224 fprintf(log_get(),"cdbios:\n");
225 fprintf(log_get(),"cdbios: track : %i\n",JaguarReadByte(addr++));
227 mm=JaguarReadByte(addr++);
228 ss=JaguarReadByte(addr++);
229 ff=JaguarReadByte(addr++);
231 fprintf(log_get(),"cdbios: start at : %.2i:%.2i:%.2i\n",mm,ss,ff);
232 fprintf(log_get(),"cdbios: session : %i\n",JaguarReadByte(addr++));
234 mm=JaguarReadByte(addr++);
235 ss=JaguarReadByte(addr++);
236 ff=JaguarReadByte(addr++);
238 fprintf(log_get(),"cdbios: duration : %.2i:%.2i:%.2i\n",mm,ss,ff);
243 void cd_bios_boot(char *filename)
248 cdi_fp=cdi_open(filename);
249 cdi_descriptor=cdi_get_descriptor(cdi_fp,log_get());
250 if (cdi_descriptor==0)
252 fprintf(log_get(),"cdi: bad image\n");
256 cdi_dump_descriptor(log_get(),cdi_descriptor);
257 cdbios_build_sector_lut();
259 uint8 *code=cdi_extract_boot_code(cdi_fp,cdi_descriptor);
261 // copy the code to ram
262 for (uint32 i=0;i<cdi_code_length;i++)
263 JaguarWriteByte(cdi_load_address+i,code[i]);
265 // set the boot address
266 JaguarWriteLong(0x00000004,cdi_load_address);
274 // fprintf(log_get(),"cdbios: boot code:\n");
275 // jaguar_dasm(cdi_load_address, cdi_code_length);
278 void cd_bios_init(void)
280 fprintf(log_get(),"cd_bios: initializing\n");
281 for (int i=0;i<19;i++)
284 JaguarWriteWord(0x3000+(i*6),0x4E70);
290 void cd_bios_reset(void)
292 fprintf(log_get(), "cd_bios: reset\n");
293 JaguarWriteWord(BIOS_VER, 0x0405);
294 cdrom_mode = CDROM_DATA_MODE;
295 cdrom_speed = CDROM_SINGLE_SPEED;
296 cdrom_oversample_factor = 1;
300 void cd_bios_done(void)
303 fprintf(log_get(), "CD BIOS: Done.\n");
306 void cdbios_cmd_init(void)
308 cdbios_init_type = CDBIOS_INIT;
309 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
310 fprintf(log_get(), "cdbios: init(0x%.8x)\n", m68k_get_reg(NULL, M68K_REG_A0));
313 void cdbios_cmd_mode(void)
315 // uint32 data = s68000context.dreg[0];
316 uint32 data = m68k_get_reg(NULL, M68K_REG_D0);
318 uint32 cdrom_mode = (data>>1) & 0x01;
319 uint32 cdrom_speed = data & 0x01;
320 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
322 // fprintf(log_get(),"cdbios: %s\n",(cdrom_mode==CDROM_AUDIO_MODE)?"audio mode":"data mode");
323 // fprintf(log_get(),"cdbios: %s\n",(cdrom_speed==CDROM_DOUBLE_SPEED)?"double speed":"single speed");
326 void cdbios_cmd_ack(void)
328 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
331 void cdbios_cmd_jeri(void)
333 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
336 void cdbios_cmd_spin(void)
338 // uint16 spin=(1<<(s68000context.dreg[0]&0xffff));
339 uint16 spin = (1 << (m68k_get_reg(NULL, M68K_REG_D0) & 0xFFFF));
340 cdbios_session = spin;
341 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
342 // fprintf(log_get(),"cdbios: switching to session %i\n",spin);
345 void cdbios_cmd_stop(void)
347 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
350 void cdbios_cmd_mute(void)
352 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
355 void cdbios_cmd_umute(void)
357 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
360 void cdbios_cmd_pause(void)
362 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
365 void cdbios_cmd_upause(void)
367 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
369 void cdi_read_block(uint32 sector, uint8 *buffer, uint32 count)
373 cdi_load_sector(cdbios_sector_lut[sector],buffer);
380 void cdbios_cmd_read(void)
382 static uint8 cdbios_sector[2352];
384 /* cdrom_destination_buffer_beginning=s68000context.areg[0];
385 cdrom_destination_buffer_end=s68000context.areg[1];
386 cdrom_time_code=(s68000context.dreg[0])&0x7fffffff;
387 cdrom_seek_only=s68000context.dreg[0]&0x80000000;*/
388 cdrom_destination_buffer_beginning = m68k_get_reg(NULL, M68K_REG_A0);
389 cdrom_destination_buffer_end = m68k_get_reg(NULL, M68K_REG_A1);
390 cdrom_time_code = m68k_get_reg(NULL, M68K_REG_D0) & 0x7FFFFFFF;
391 cdrom_seek_only = m68k_get_reg(NULL, M68K_REG_D0) & 0x80000000;
393 /* cdrom_partition_marker=s68000context.dreg[1];
394 if (s68000context.dreg[2]!=0)
395 cdrom_circular_buffer_size=(1<<s68000context.dreg[2]);*/
396 cdrom_partition_marker = m68k_get_reg(NULL, M68K_REG_D1);
397 if (m68k_get_reg(NULL, M68K_REG_D2) != 0)
398 cdrom_circular_buffer_size = 1 << m68k_get_reg(NULL, M68K_REG_D2);
400 cdrom_circular_buffer_size = 0xFFFFFFFF; // no circular buffer;
402 uint32 mm = (10 * ((cdrom_time_code >> 20) & 0x0F)) + ((cdrom_time_code >> 16) & 0x0F);
403 uint32 ss = (10 * ((cdrom_time_code >> 12) & 0x0F)) + ((cdrom_time_code >> 8) & 0x0F);
404 uint32 ff = (10 * ((cdrom_time_code >> 4) & 0x0F)) + ((cdrom_time_code >> 0) & 0x0F);
406 fprintf(log_get(),"cdbios: read(0x%.8x, 0x%.8x, %.2i:%.2i:%.2i, %i) %s\n",
407 cdrom_destination_buffer_beginning,
408 cdrom_destination_buffer_end,
410 cdrom_circular_buffer_size,cdrom_seek_only?"(seek only)":"");
412 if (!cdrom_seek_only)
414 if (cdbios_init_type==CDBIOS_INITM)
416 fprintf(log_get(),"cdbios: partition marker: %c%c%c%c (0x%.8x)\n",
417 ((cdrom_partition_marker>>24)&0xff),
418 ((cdrom_partition_marker>>16)&0xff),
419 ((cdrom_partition_marker>>8)&0xff),
420 (cdrom_partition_marker&0xff),
421 cdrom_partition_marker
424 if (((int32)cdrom_circular_buffer_size)==-1)
425 cdrom_circular_buffer_size=0xffffffff;
427 uint32 track_offset=((ss+(60*mm))*75)+ff;
429 fprintf(log_get(),"cdbios: track offset: %i\n",track_offset);
430 uint32 nb_sectors=(cdrom_destination_buffer_end-cdrom_destination_buffer_beginning)/2352;
431 uint32 reste=(cdrom_destination_buffer_end-cdrom_destination_buffer_beginning)%2352;
432 uint32 buffer_offset=0;
433 uint32 nb_bytes_to_read=cdrom_destination_buffer_end-cdrom_destination_buffer_beginning+1;
435 if (cdbios_init_type==CDBIOS_INITF)
437 // if (cdrom_destination_buffer_beginning==0x00046000)
440 uint8 *buffer=(uint8*)malloc((nb_sectors+1)*2352);
441 cdi_read_block(track_offset,buffer,nb_sectors+1);
442 for (uint32 k=0;k<nb_bytes_to_read;k++)
443 JaguarWriteByte(cdrom_destination_buffer_beginning+k,buffer[k]);
447 if (cdbios_init_type==CDBIOS_INITM)
449 uint8 *buffer=(uint8*)malloc((31+nb_sectors+1)*2352);
450 cdi_read_block(track_offset,buffer,nb_sectors+1);
452 uint32 count=(31+nb_sectors+1)*2352;
454 uint32 marker_count=2;
459 (alias[0]==((cdrom_partition_marker>>24)&0xff))&&
460 (alias[1]==((cdrom_partition_marker>>16)&0xff))&&
461 (alias[2]==((cdrom_partition_marker>>8)&0xff))&&
462 (alias[3]==((cdrom_partition_marker>>0)&0xff))
474 for (uint32 k=0;k<nb_bytes_to_read;k++)
475 JaguarWriteByte(cdrom_destination_buffer_beginning+k,alias[k]);
487 fprintf(log_get(),"cdbios: unsupported read mode\n");
490 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
493 void cdbios_cmd_uread(void)
495 // stop the recording started with a cd_read command
496 // for now, there is nothing to do
497 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
500 void cdbios_cmd_setup(void)
502 // initialize the cd system
503 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
506 void cdbios_cmd_ptr(void)
508 // s68000context.areg[0]=cdrom_destination_buffer_end+4;
509 m68k_set_reg(M68K_REG_A0, cdrom_destination_buffer_end + 4);
510 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
513 void cdbios_cmd_osamp(void)
515 // cdrom_oversample_factor=(1<<(s68000context.dreg[0]&0xffff));
516 cdrom_oversample_factor = 1 << (m68k_get_reg(NULL, M68K_REG_D0) & 0xFFFF);
517 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
520 void cdbios_cmd_gettoc(void)
522 JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
525 void cdbios_cmd_initm(void)
527 cdbios_init_type = CDBIOS_INITM;
528 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
529 // fprintf(log_get(),"cdbios: initm(0x%.8x)\n",s68000context.areg[0]);
530 fprintf(log_get(), "cdbios: initm(0x%.8x)\n", m68k_get_reg(NULL, M68K_REG_A0));
533 void cdbios_cmd_initf(void)
535 cdbios_init_type = CDBIOS_INITF;
536 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
537 // fprintf(log_get(),"cdbios: initf(0x%.8x)\n",s68000context.areg[0]);
538 fprintf(log_get(), "cdbios: initf(0x%.8x)\n", m68k_get_reg(NULL, M68K_REG_A0));
541 void cd_bios_process(uint32 offset)
543 if (!cdbios_init_done)
546 fprintf(log_get(), "cdbios: processing command '%s'\n", cdbios_command[(offset-0x3000) / 6]);
547 fprintf(log_get(), "cdbios: 68K PC=%08X SP=%08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)), m68k_get_reg(NULL, M68K_REG_A7));
551 case CD_INIT: cdbios_cmd_init(); break;
552 case CD_MODE: cdbios_cmd_mode(); break;
553 case CD_ACK: cdbios_cmd_ack(); break;
554 case CD_JERI: cdbios_cmd_jeri(); break;
555 case CD_SPIN: cdbios_cmd_spin(); break;
556 case CD_STOP: cdbios_cmd_stop(); break;
557 case CD_MUTE: cdbios_cmd_mute(); break;
558 case CD_UMUTE: cdbios_cmd_umute(); break;
559 case CD_PAUSE: cdbios_cmd_pause(); break;
560 case CD_UPAUSE: cdbios_cmd_upause(); break;
561 case CD_READ: cdbios_cmd_read(); break;
562 case CD_UREAD: cdbios_cmd_uread(); break;
563 case CD_SETUP: cdbios_cmd_setup(); break;
564 case CD_PTR: cdbios_cmd_ptr(); break;
565 case CD_OSAMP: cdbios_cmd_osamp(); break;
566 case CD_GETTOC: cdbios_cmd_gettoc(); break;
567 case CD_INITM: cdbios_cmd_initm(); break;
568 case CD_INITF: cdbios_cmd_initf(); break;
570 default: fprintf(log_get(), "cdbios: unemulated entry point at %08X 68K PC=%08X SP=%08X\n", offset, JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)), m68k_get_reg(NULL, M68K_REG_A7));
571 JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
575 // s68000context.pc=JaguarReadLong(s68000context.areg[7]);
576 // s68000context.areg[7]=(s68000context.areg[7]+4)&0xffffffff;
577 m68k_set_reg(M68K_REG_PC, JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
578 m68k_set_reg(M68K_REG_A7, (m68k_get_reg(NULL, M68K_REG_A7) + 4) & 0xFFFFFFFF);
581 void cd_bios_exec(uint32 scanline)
583 // single speed mode: 150 Kb/s (153600 bytes/s)
584 // single speed mode: 300 Kb/s (307200 bytes/s)
585 uint32 bytes_per_scanline=(153600*((cdrom_speed==CDROM_DOUBLE_SPEED)?2:1))/525;