]> Shamusworld >> Repos - virtualjaguar/blob - src/cdbios.cpp
Support for new timer based execution
[virtualjaguar] / src / cdbios.cpp
1 //
2 // CD BIOS core
3 //
4 // by David Raingeard
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups by James L. Hammons
7 //
8 // David R.:
9 // 02/20/2002: Fixed sector to MSF conversion
10 // 02/19/2002: Fixed a bug in TOC encoding function
11 //
12
13 #include "cdbios.h"
14
15 /* Added by SDLEMU (http://sdlemu.ngemu.com */
16 /* Some GCC UNIX includes                   */
17 #ifdef __GCCUNIX__
18 #include <unistd.h>
19 #endif
20
21 #define ERR_FLAG        0x3e00
22 #define CD_TOC          0x2c00
23 #define BIOS_VER    0x3004
24
25 #define CDBIOS_INIT             0
26 #define CDBIOS_INITM    1
27 #define CDBIOS_INITF    2
28
29 #define CD_INIT         0x3000
30 #define CD_MODE         0x3006
31 #define CD_ACK          0x300C
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
42 #define CD_PTR          0x304E
43 #define CD_OSAMP        0x3054
44 #define CD_GETTOC       0x306A
45 #define CD_INITM        0x3060
46 #define CD_INITF        0x3066
47
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 };
52
53 #define CDROM_AUDIO_MODE        0
54 #define CDROM_DATA_MODE         1
55
56 #define CDROM_SINGLE_SPEED      0
57 #define CDROM_DOUBLE_SPEED  1
58
59 #define CDROM_STATUS_OK         0
60 #define CDROM_STATUS_ERROR      1
61
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;
66
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;
73
74 uint32 cdbios_init_type;
75 uint32 * cdbios_sector_lut;
76 uint32 cdbios_init_done = 0;
77
78
79 void cdbios_build_sector_lut(void)
80 {
81         uint32 last_sector=0;
82         int32 offset=0;
83         uint32 sector=0;
84
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];
86         
87         last_sector=last_track->start_lba+last_track->total_length-1;
88
89
90         cdbios_sector_lut=(uint32*)malloc((last_sector+1)*sizeof(uint32));
91         memset(cdbios_sector_lut,0xff,(last_sector+1)*sizeof(uint32));
92
93         for (int session=0;session<cdi_descriptor->nb_of_sessions;session++)
94         {
95                 for (int track=0;track<cdi_descriptor->sessions[session].nb_of_tracks;track++)
96                 {
97                         s_cdi_track *current_track=&cdi_descriptor->sessions[session].tracks[track];
98
99                         if (offset<((int32)(current_track->start_lba-1)))
100                         {
101                                 fprintf(log_get(),"cdbios: postgap between %i and %i\n",offset,current_track->start_lba-1);
102
103                                 // fill-in postgap
104                                 for (;offset<current_track->start_lba;offset++)
105                                 {
106                                         cdbios_sector_lut[offset]=0xffffffff;
107                                 }
108
109                         }                       
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++)
112                         {
113                                 cdbios_sector_lut[offset]=sector;
114                                 sector++;
115                         }
116
117                 }
118         }
119
120 }
121
122 void cdbios_get_time(uint32 sectors, uint32 *mm, uint32 *ss, uint32 *ff)
123 {
124         uint32 _sectors=sectors;
125
126         uint32 _mm=(sectors/(60*75));
127         sectors-=(_mm*(60*75));
128         uint32 _ss=(sectors/75);
129         sectors-=(_ss*75);
130         uint32 _ff=sectors;
131
132         *mm=_mm;
133         *ss=_ss;
134         *ff=_ff;
135         
136
137 //      fprintf(log_get(),"[%.2i:%.2i:%.2i]\n",_mm,_ss,_ff);
138 }
139
140 void cdbios_encode_toc(void)
141 {
142         int i;
143         uint32 base=CD_TOC;
144
145         JaguarWriteByte(base++,0x00);
146         JaguarWriteByte(base++,0x00);
147         JaguarWriteByte(base++,0x01);
148
149         int nbtracks=0;
150         for (i=0;i<cdi_descriptor->nb_of_sessions;i++)
151                 nbtracks+=cdi_descriptor->sessions[i].nb_of_tracks;
152
153         JaguarWriteByte(base++,nbtracks+1);
154         JaguarWriteByte(base++,cdi_descriptor->nb_of_sessions);
155         
156         uint32 mm=0;
157         uint32 ss=0;
158         uint32 ff=0;
159
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,
163                                         &mm,&ss,&ff);
164
165         JaguarWriteByte(base++,mm);
166         JaguarWriteByte(base++,ss);
167         JaguarWriteByte(base++,ff);
168
169         int track_count=1;
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++)
172                 {
173                         s_cdi_track *track=&cdi_descriptor->sessions[i].tracks[j];
174                         
175 //                      fprintf(log_get(),"track %i\n",track_count);
176
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);
187                                 
188                         track_count++;
189                 }
190
191         cdi_tracks_count=track_count;
192         cdi_tracks=(s_cdi_track**)malloc(track_count*sizeof(s_cdi_track*));
193         track_count=0;
194         for (i=0;i<cdi_descriptor->nb_of_sessions;i++)
195         {
196                 for (int j=0;j<cdi_descriptor->sessions[i].nb_of_tracks;j++)
197                 {
198                         cdi_tracks[track_count]=&cdi_descriptor->sessions[i].tracks[j];
199                         track_count++;
200                 }
201         }
202 }
203
204 void cdbios_decode_toc(void)
205 {
206         uint32 addr=0x2c00;
207         uint32 nb_tracks;
208         
209         fprintf(log_get(),"cdbios: toc:\n");
210         fprintf(log_get(),"cdbios:\n");
211         addr+=2;
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++));
217
218         uint32 mm,ss,ff;
219
220         nb_tracks--;
221
222         while (nb_tracks)
223         {
224                 fprintf(log_get(),"cdbios:\n");
225                 fprintf(log_get(),"cdbios: track          : %i\n",JaguarReadByte(addr++));
226                 
227                 mm=JaguarReadByte(addr++);
228                 ss=JaguarReadByte(addr++);
229                 ff=JaguarReadByte(addr++);
230
231                 fprintf(log_get(),"cdbios: start at       : %.2i:%.2i:%.2i\n",mm,ss,ff);
232                 fprintf(log_get(),"cdbios: session        : %i\n",JaguarReadByte(addr++));
233                 
234                 mm=JaguarReadByte(addr++);
235                 ss=JaguarReadByte(addr++);
236                 ff=JaguarReadByte(addr++);
237
238                 fprintf(log_get(),"cdbios: duration       : %.2i:%.2i:%.2i\n",mm,ss,ff);
239                 nb_tracks--;
240         }
241 }
242
243 void cd_bios_boot(char *filename)
244 {
245         cd_bios_init();
246
247
248         cdi_fp=cdi_open(filename);
249         cdi_descriptor=cdi_get_descriptor(cdi_fp,log_get());
250         if (cdi_descriptor==0)
251         {
252                 fprintf(log_get(),"cdi: bad image\n");
253                 cdi_close(cdi_fp);
254                 return;
255         }
256         cdi_dump_descriptor(log_get(),cdi_descriptor);
257         cdbios_build_sector_lut();
258
259         uint8 *code=cdi_extract_boot_code(cdi_fp,cdi_descriptor);
260
261         // copy the code to ram
262         for (uint32 i=0;i<cdi_code_length;i++)
263                 JaguarWriteByte(cdi_load_address+i,code[i]);
264
265         // set the boot address
266         JaguarWriteLong(0x00000004,cdi_load_address);
267
268         // write the toc
269         cdbios_encode_toc();
270
271         // dump the toc
272         cdbios_decode_toc();
273
274 //      fprintf(log_get(),"cdbios: boot code:\n");
275 //      jaguar_dasm(cdi_load_address, cdi_code_length);
276 }
277
278 void cd_bios_init(void)
279 {
280         fprintf(log_get(),"cd_bios: initializing\n");
281         for (int i=0;i<19;i++)
282         {
283                 // RESET opcode
284                 JaguarWriteWord(0x3000+(i*6),0x4E70);
285         }
286         cd_bios_reset();
287         cdbios_init_done=1;
288 }
289
290 void cd_bios_reset(void)
291 {
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;
297         cdbios_session                  = 0;
298 }
299
300 void cd_bios_done(void)
301 {
302         close(cdi_fp);
303         fprintf(log_get(), "CD BIOS: Done.\n");
304 }
305
306 void cdbios_cmd_init(void)
307 {
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));
311 }
312
313 void cdbios_cmd_mode(void)
314 {
315 //      uint32 data = s68000context.dreg[0];
316         uint32 data = m68k_get_reg(NULL, M68K_REG_D0);
317
318         uint32 cdrom_mode = (data>>1) & 0x01;
319         uint32 cdrom_speed = data & 0x01;
320         JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
321
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");
324 }
325
326 void cdbios_cmd_ack(void)
327 {
328     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
329 }
330
331 void cdbios_cmd_jeri(void)
332 {
333     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
334 }
335
336 void cdbios_cmd_spin(void)
337 {
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);
343 }
344
345 void cdbios_cmd_stop(void)
346 {
347     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
348 }
349
350 void cdbios_cmd_mute(void)
351 {
352     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
353 }
354
355 void cdbios_cmd_umute(void)
356 {
357     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
358 }
359
360 void cdbios_cmd_pause(void)
361 {
362     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
363 }
364
365 void cdbios_cmd_upause(void)
366 {
367     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
368 }
369 void cdi_read_block(uint32 sector, uint8 *buffer, uint32 count)
370 {
371         while (count)
372         {
373                 cdi_load_sector(cdbios_sector_lut[sector],buffer);
374                 buffer+=2352;
375                 sector++;
376                 count--;
377         }
378 }
379
380 void cdbios_cmd_read(void)
381 {
382         static uint8 cdbios_sector[2352];
383
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;
392
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);
399         else
400                 cdrom_circular_buffer_size = 0xFFFFFFFF; // no circular buffer;
401
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);
405
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,
409                                                 mm,ss,ff,
410                                                 cdrom_circular_buffer_size,cdrom_seek_only?"(seek only)":"");
411
412         if (!cdrom_seek_only)
413         {
414                 if (cdbios_init_type==CDBIOS_INITM)
415                 {
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
422                                 );
423                 }
424                 if (((int32)cdrom_circular_buffer_size)==-1)
425                         cdrom_circular_buffer_size=0xffffffff;
426
427                 uint32 track_offset=((ss+(60*mm))*75)+ff;
428
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;
434
435                 if (cdbios_init_type==CDBIOS_INITF)
436                 {
437 //                      if (cdrom_destination_buffer_beginning==0x00046000)
438 //                              return;
439
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]);
444                         free(buffer);
445                 }
446                 else
447                 if (cdbios_init_type==CDBIOS_INITM)
448                 {
449                         uint8 *buffer=(uint8*)malloc((31+nb_sectors+1)*2352);
450                         cdi_read_block(track_offset,buffer,nb_sectors+1);
451                         
452                         uint32  count=(31+nb_sectors+1)*2352;
453                         uint8   *alias=buffer;
454                         uint32  marker_count=2;
455
456                         while (count-4)
457                         {
458                                 if (
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))
463                                         )
464                                 {
465                                         marker_count--;
466                                         if (marker_count)
467                                         {
468                                                 alias+=3;
469                                         }
470                                         else
471                                         {
472                                                 exit(0);
473                                                 alias+=4;
474                                                 for (uint32 k=0;k<nb_bytes_to_read;k++)
475                                                         JaguarWriteByte(cdrom_destination_buffer_beginning+k,alias[k]);
476                                                 free(buffer);
477                                                 return;
478                                         }
479                                 }
480                                 alias++;
481                                 count--;
482                         }
483                         free(buffer);
484                 }
485                 else
486                 {
487                         fprintf(log_get(),"cdbios: unsupported read mode\n");
488                 }
489         }
490     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
491 }
492
493 void cdbios_cmd_uread(void)
494 {
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);
498 }
499
500 void cdbios_cmd_setup(void)
501 {
502         // initialize the cd system
503     JaguarWriteWord(ERR_FLAG, CDROM_STATUS_OK);
504 }
505
506 void cdbios_cmd_ptr(void)
507 {
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);
511 }
512
513 void cdbios_cmd_osamp(void)
514 {
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);
518 }
519
520 void cdbios_cmd_gettoc(void)
521 {
522     JaguarWriteWord(ERR_FLAG,CDROM_STATUS_OK);
523 }
524
525 void cdbios_cmd_initm(void)
526 {
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));
531 }
532
533 void cdbios_cmd_initf(void)
534 {
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));
539 }
540
541 void cd_bios_process(uint32 offset)
542 {
543         if (!cdbios_init_done)
544                 return;
545
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));
548
549         switch (offset)
550         {
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;
569
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);
572         }
573
574         // rts
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);
579 }
580
581 void cd_bios_exec(uint32 scanline)
582 {
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;
586 }