Fixed a crash, in Release mode, when the HW labels setting is turned on.
[clinton/Virtual-Jaguar-Rx.git] / src / cdrom.cpp
CommitLineData
cf76e892
JPM
1//
2// CD handler
3//
4// Originally by David Raingeard
5// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6// Extensive rewrites/cleanups/fixes by James Hammons
7// (C) 2010 Underground Software
8//
9// JLH = James Hammons <jlhamm@acm.org>
10//
11// Who When What
12// --- ---------- ------------------------------------------------------------
13// JLH 01/16/2010 Created this log ;-)
14//
15
16#include "cdrom.h"
17
18#include <string.h> // For memset, etc.
19//#include "jaguar.h" // For GET32/SET32 macros
20//#include "m68k.h" //???
21//#include "memory.h"
22#include "cdintf.h" // System agnostic CD interface functions
23#include "log.h"
24#include "dac.h"
25
26//#define CDROM_LOG // For CDROM logging, obviously
27
28/*
29BUTCH equ $DFFF00 ; base of Butch=interrupt control register, R/W
30DSCNTRL equ BUTCH+4 ; DSA control register, R/W
31DS_DATA equ BUTCH+$A ; DSA TX/RX data, R/W
32I2CNTRL equ BUTCH+$10 ; i2s bus control register, R/W
33SBCNTRL equ BUTCH+$14 ; CD subcode control register, R/W
34SUBDATA equ BUTCH+$18 ; Subcode data register A
35SUBDATB equ BUTCH+$1C ; Subcode data register B
36SB_TIME equ BUTCH+$20 ; Subcode time and compare enable (D24)
37FIFO_DATA equ BUTCH+$24 ; i2s FIFO data
38I2SDAT1 equ BUTCH+$24 ; i2s FIFO data
39I2SDAT2 equ BUTCH+$28 ; i2s FIFO data
40 equ BUTCH+$2C ; CD EEPROM interface
41
42;
43; Butch's hardware registers
44;
45;BUTCH equ $DFFF00 ;base of Butch=interrupt control register, R/W
46;
47; When written (Long):
48;
49; bit0 - set to enable interrupts
50; bit1 - enable CD data FIFO half full interrupt
51; bit2 - enable CD subcode frame-time interrupt (@ 2x spped = 7ms.)
52; bit3 - enable pre-set subcode time-match found interrupt
53; bit4 - CD module command transmit buffer empty interrupt
54; bit5 - CD module command receive buffer full
55; bit6 - CIRC failure interrupt
56;
57; bit7-31 reserved, set to 0
58;
59; When read (Long):
60;
61; bit0-8 reserved
62;
63; bit9 - CD data FIFO half-full flag pending
64; bit10 - Frame pending
65; bit11 - Subcode data pending
66; bit12 - Command to CD drive pending (trans buffer empty if 1)
67; bit13 - Response from CD drive pending (rec buffer full if 1)
68; bit14 - CD uncorrectable data error pending
69;
70; Offsets from BUTCH
71;
72O_DSCNTRL equ 4 ; DSA control register, R/W
73O_DS_DATA equ $A ; DSA TX/RX data, R/W
74;
75O_I2CNTRL equ $10 ; i2s bus control register, R/W
76;
77; When read:
78;
79; b0 - I2S data from drive is ON if 1
80; b1 - I2S path to Jerry is ON if 1
81; b2 - reserved
82; b3 - host bus width is 16 if 1, else 32
83; b4 - FIFO state is not empty if 1
84;
85O_SBCNTRL equ $14 ; CD subcode control register, R/W
86O_SUBDATA equ $18 ; Subcode data register A
87O_SUBDATB equ $1C ; Subcode data register B
88O_SB_TIME equ $20 ; Subcode time and compare enable (D24)
89O_FIFODAT equ $24 ; i2s FIFO data
90O_I2SDAT2 equ $28 ; i2s FIFO data (old)
91*/
92
93/*
94Commands sent through DS_DATA:
95
96$01nn - ? Play track nn ? Seek to track nn ?
97$0200 - Stop CD
98$03nn - Read session nn TOC (short)
99$0400 - Pause CD
100$0500 - Unpause CD
101$10nn - Goto (min?)
102$11nn - Goto (sec?)
103$12nn - Goto (frm?)
104$14nn - Read session nn TOC (full)
105$15nn - Set CD mode
106$18nn - Spin up CD to session nn
107$5000 - ?
108$5100 - Mute CD (audio mode only)
109$51FF - Unmute CD (audio mode only)
110$5400 - Read # of sessions on CD
111$70nn - Set oversampling mode
112
113Commands send through serial bus:
114
115$100 - ? Acknowledge ? (Erase/Write disable)
116$130 - ? (Seems to always prefix the $14n commands) (Erase/Write enable)
117$140 - Returns ACK (1) (Write to NVRAM?) (Write selected register)
118$141 - Returns ACK (1)
119$142 - Returns ACK (1)
120$143 - Returns ACK (1)
121$144 - Returns ACK (1)
122$145 - Returns ACK (1)
123$180 - Returns 16-bit value (NVRAM?) (read from EEPROM)
124$181 - Returns 16-bit value
125$182 - Returns 16-bit value
126$183 - Returns 16-bit value
127$184 - Returns 16-bit value
128$185 - Returns 16-bit value
129
130; The BUTCH interface for the CD-ROM module is a long-word register,
131; where only the least signifigant 4 bits are used
132;
133eeprom equ $DFFF2c ;interface to CD-eeprom
134;
135; bit3 - busy if 0 after write cmd, or Data In after read cmd
136; bit2 - Data Out
137; bit1 - clock
138; bit0 - Chip Select (CS)
139;
140;
141; Commands specific to the National Semiconductor NM93C14
142;
143;
144; 9-bit commands..
145; 876543210
146eREAD equ %110000000 ;read from EEPROM
147eEWEN equ %100110000 ;Erase/write Enable
148eERASE equ %111000000 ;Erase selected register
149eWRITE equ %101000000 ;Write selected register
150eERAL equ %100100000 ;Erase all registers
151eWRAL equ %100010000 ;Writes all registers
152eEWDS equ %100000000 ;Erase/Write disable (default)
153
154So... are there $40 words of memory? 128 bytes?
155
156*/
157
158// Private function prototypes
159
160static void CDROMBusWrite(uint16_t);
161static uint16_t CDROMBusRead(void);
162
163#define BUTCH 0x00 // base of Butch == interrupt control register, R/W
164#define DSCNTRL BUTCH + 0x04 // DSA control register, R/W
165#define DS_DATA BUTCH + 0x0A // DSA TX/RX data, R/W
166#define I2CNTRL BUTCH + 0x10 // i2s bus control register, R/W
167#define SBCNTRL BUTCH + 0x14 // CD subcode control register, R/W
168#define SUBDATA BUTCH + 0x18 // Subcode data register A
169#define SUBDATB BUTCH + 0x1C // Subcode data register B
170#define SB_TIME BUTCH + 0x20 // Subcode time and compare enable (D24)
171#define FIFO_DATA BUTCH + 0x24 // i2s FIFO data
172#define I2SDAT2 BUTCH + 0x28 // i2s FIFO data (old)
173#define UNKNOWN BUTCH + 0x2C // Seems to be some sort of I2S interface
174
175const char * BReg[12] = { "BUTCH", "DSCNTRL", "DS_DATA", "???", "I2CNTRL",
176 "SBCNTRL", "SUBDATA", "SUBDATB", "SB_TIME", "FIFO_DATA", "I2SDAT2",
177 "UNKNOWN" };
178//extern const char * whoName[9];
179
180
181static uint8_t cdRam[0x100];
182static uint16_t cdCmd = 0, cdPtr = 0;
183static bool haveCDGoodness;
184static uint32_t min, sec, frm, block;
185static uint8_t cdBuf[2352 + 96];
186static uint32_t cdBufPtr = 2352;
187//Also need to set up (save/restore) the CD's NVRAM
188
189
190//extern bool GetRawTOC(void);
191void CDROMInit(void)
192{
193 haveCDGoodness = CDIntfInit();
194
195//GetRawTOC();
196/*uint8_t buf[2448];
197uint32_t sec = 18667 - 150;
198memset(buf, 0, 2448);
199if (!CDIntfReadBlock(sec, buf))
200{
201 WriteLog("CDROM: Attempt to read with subchannel data failed!\n");
202 return;
203}
204
205//24x98+96
206//96=4x24=4x4x6
207WriteLog("\nCDROM: Read sector %u...\n\n", sec);
208for(int i=0; i<98; i++)
209{
210 WriteLog("%04X: ", i*24);
211 for(int j=0; j<24; j++)
212 {
213 WriteLog("%02X ", buf[j + (i*24)]);
214 }
215 WriteLog("\n");
216}
217WriteLog("\nRaw P-W subchannel data:\n\n");
218for(int i=0; i<6; i++)
219{
220 WriteLog("%02X: ", i*16);
221 for(int j=0; j<16; j++)
222 {
223 WriteLog("%02X ", buf[2352 + j + (i*16)]);
224 }
225 WriteLog("\n");
226}
227WriteLog("\nP subchannel data: ");
228for(int i=0; i<96; i+=8)
229{
230 uint8_t b = 0;
231 for(int j=0; j<8; j++)
232 b |= ((buf[2352 + i + j] & 0x80) >> 7) << (7 - j);
233
234 WriteLog("%02X ", b);
235}
236WriteLog("\nQ subchannel data: ");
237for(int i=0; i<96; i+=8)
238{
239 uint8_t b = 0;
240 for(int j=0; j<8; j++)
241 b |= ((buf[2352 + i + j] & 0x40) >> 6) << (7 - j);
242
243 WriteLog("%02X ", b);
244}
245WriteLog("\n\n");//*/
246}
247
248void CDROMReset(void)
249{
250 memset(cdRam, 0x00, 0x100);
251 cdCmd = 0;
252}
253
254void CDROMDone(void)
255{
256 CDIntfDone();
257}
258
259
260//
261// This approach is probably wrong, but let's do it for now.
262// What's needed is a complete overhaul of the interrupt system so that
263// interrupts are handled as they're generated--instead of the current
264// scheme where they're handled on scanline boundaries.
265//
266void BUTCHExec(uint32_t cycles)
267{
268#if 1
269// We're chickening out for now...
270return;
271#else
272// extern uint8_t * jerry_ram_8; // Hmm.
273
274 // For now, we just do the FIFO interrupt. Timing is also likely to be WRONG as well.
275 uint32_t cdState = GET32(cdRam, BUTCH);
276
277 if (!(cdState & 0x01)) // No BUTCH interrupts enabled
278 return;
279
280 if (!(cdState & 0x22))
281 return; // For now, we only handle FIFO/buffer full interrupts...
282
283 // From what I can make out, it seems that each FIFO is 32 bytes long
284
285// DSPSetIRQLine(DSPIRQ_EXT, ASSERT_LINE);
286//I'm *sure* this is wrong--prolly need to generate DSP IRQs as well!
287 if (jerry_ram_8[0x23] & 0x3F) // Only generate an IRQ if enabled!
288 GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE);
289#endif
290}
291
292
293//
294// CD-ROM memory access functions
295//
296
297uint8_t CDROMReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
298{
299#ifdef CDROM_LOG
300 if ((offset & 0xFF) < 12 * 4)
301 WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]);
302 WriteLog("CDROM: %s reading byte $%02X from $%08X [68K PC=$%08X]\n", whoName[who], offset, cdRam[offset & 0xFF], m68k_get_reg(NULL, M68K_REG_PC));
303#endif
304 return cdRam[offset & 0xFF];
305}
306
307static uint8_t trackNum = 1, minTrack, maxTrack;
308//static uint8_t minutes[16] = { 0, 0, 2, 5, 7, 10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35 };
309//static uint8_t seconds[16] = { 0, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0 };
310//static uint8_t frames[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
311//static uint16_t sd = 0;
312uint16_t CDROMReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
313{
314 offset &= 0xFF;
315
316 uint16_t data = 0x0000;
317
318 if (offset == BUTCH)
319 data = 0x0000;
320 else if (offset == BUTCH + 2)
321// We need to fix this so it's not as brain-dead as it is now--i.e., make it so that when
322// a command is sent to the CDROM, we control here whether or not it succeeded or whether
323// the command is still being carried out, etc.
324
325// bit12 - Command to CD drive pending (trans buffer empty if 1)
326// bit13 - Response from CD drive pending (rec buffer full if 1)
327// data = (haveCDGoodness ? 0x3000 : 0x0000); // DSA RX Interrupt pending bit (0 = pending)
328//This only returns ACKs for interrupts that are set:
329//This doesn't work for the initial code that writes $180000 to BUTCH. !!! FIX !!!
330 data = (haveCDGoodness ? cdRam[BUTCH + 3] << 8 : 0x0000);
331// else if (offset == SUBDATA + 2)
332// data = sd++ | 0x0010; // Have no idea what this is...
333 else if (offset == DS_DATA && haveCDGoodness)
334 {
335 if ((cdCmd & 0xFF00) == 0x0100) // ???
336 {
337//Not sure how to acknowledge the ???...
338// data = 0x0400;//?? 0x0200;
339 cdPtr++;
340 switch (cdPtr)
341 {
342 case 1:
343 data = 0x0000;
344 break;
345 case 2:
346 data = 0x0100;
347 break;
348 case 3:
349 data = 0x0200;
350 break;
351 case 4:
352 data = 0x0300;
353 break;
354 case 5:
355 data = 0x0400;
356 }//*/
357 WriteLog("CDROM: Reading DS_DATA (???), cdCmd=$%04X\n", cdCmd);
358 }
359 else if ((cdCmd & 0xFF00) == 0x0200) // Stop CD
360 {
361//Not sure how to acknowledge the stop...
362 data = 0x0400;//?? 0x0200;
363/* cdPtr++;
364 switch (cdPtr)
365 {
366 case 1:
367 data = 0x00FF;
368 break;
369 case 2:
370 data = 0x01FF;
371 break;
372 case 3:
373 data = 0x02FF;
374 break;
375 case 4:
376 data = 0x03FF;
377 break;
378 case 5:
379 data = 0x0400;
380 }//*/
381 WriteLog("CDROM: Reading DS_DATA (stop), cdCmd=$%04X\n", cdCmd);
382 }
383 else if ((cdCmd & 0xFF00) == 0x0300) // Read session TOC (overview?)
384 {
385
386/*
387TOC: [Sess] [adrCtl] [?] [point] [?] [?] [?] [?] [pmin] [psec] [pframe]
388TOC: 1 10 00 a0 00:00:00 00 01:00:00
389TOC: 1 10 00 a1 00:00:00 00 01:00:00
390TOC: 1 10 00 a2 00:00:00 00 03:42:42
391TOC: 1 10 00 1 00:00:00 00 00:02:00 <-- Track #1
392TOC: 1 50 00 b0 06:12:42 02 79:59:74
393TOC: 1 50 00 c0 128:00:32 00 97:18:06
394TOC: 2 10 00 a0 00:00:00 00 02:00:00
395TOC: 2 10 00 a1 00:00:00 00 11:00:00
396TOC: 2 10 00 a2 00:00:00 00 54:32:18
397TOC: 2 10 00 2 00:00:00 00 06:14:42 <-- Track #2
398TOC: 2 10 00 3 00:00:00 00 06:24:42 <-- Track #3
399TOC: 2 10 00 4 00:00:00 00 17:42:00 <-- Track #4
400TOC: 2 10 00 5 00:00:00 00 22:26:15 <-- Track #5
401TOC: 2 10 00 6 00:00:00 00 29:50:16 <-- Track #6
402TOC: 2 10 00 7 00:00:00 00 36:01:49 <-- Track #7
403TOC: 2 10 00 8 00:00:00 00 40:37:59 <-- Track #8
404TOC: 2 10 00 9 00:00:00 00 45:13:70 <-- Track #9
405TOC: 2 10 00 a 00:00:00 00 49:50:06 <-- Track #10
406TOC: 2 10 00 b 00:00:00 00 54:26:17 <-- Track #11
407*/
408
409//Should do something like so:
410// data = GetSessionInfo(cdCmd & 0xFF, cdPtr);
411 data = CDIntfGetSessionInfo(cdCmd & 0xFF, cdPtr);
412 if (data == 0xFF) // Failed...
413 {
414 data = 0x0400;
415 WriteLog("CDROM: Requested invalid session #%u (or failed to load TOC, or bad cdPtr value)\n", cdCmd & 0xFF);
416 }
417 else
418 {
419 data |= (0x20 | cdPtr++) << 8;
420 WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd & 0xFF, cdPtr, data);
421 }
422
423/* bool isValidSession = ((cdCmd & 0xFF) == 0 ? true : false);//Hardcoded... !!! FIX !!!
424//NOTE: This should return error condition if the requested session doesn't exist! ($0400?)
425 if (isValidSession)
426 {
427 cdPtr++;
428 switch (cdPtr)
429 {
430 case 1:
431 data = 0x2001; // Min track for this session?
432 break;
433 case 2:
434 data = 0x210A; // Max track for this session?
435 break;
436 case 3:
437 data = 0x2219; // Max lead-out time, absolute minutes
438 break;
439 case 4:
440 data = 0x2319; // Max lead-out time, absolute seconds
441 break;
442 case 5:
443 data = 0x2419; // Max lead-out time, absolute frames
444 break;
445 default:
446 data = 0xFFFF;
447
448//; +0 - unused, reserved (0)
449//; +1 - unused, reserved (0)
450//; +2 - minimum track number
451//; +3 - maximum track number
452//; +4 - total number of sessions
453//; +5 - start of last lead-out time, absolute minutes
454//; +6 - start of last lead-out time, absolute seconds
455//; +7 - start of last lead-out time, absolute frames
456
457 }
458 WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd & 0xFF, cdPtr, data);
459 }
460 else
461 {
462 data = 0x0400;
463 WriteLog("CDROM: Requested invalid session #%u\n", cdCmd & 0xFF);
464 }*/
465 }
466 // Seek to m, s, or f position
467 else if ((cdCmd & 0xFF00) == 0x1000 || (cdCmd & 0xFF00) == 0x1100 || (cdCmd & 0xFF00) == 0x1200)
468 data = 0x0100; // Success, though this doesn't take error handling into account.
469 // Ideally, we would also set the bits in BUTCH to let the processor know that
470 // this is ready to be read... !!! FIX !!!
471 else if ((cdCmd & 0xFF00) == 0x1400) // Read "full" session TOC
472 {
473//Need to be a bit more tricky here, since it's reading the "session" TOC instead of the
474//full TOC--so we need to check for the min/max tracks for each session here... [DONE]
475
476 if (trackNum > maxTrack)
477 {
478 data = 0x400;
479WriteLog("CDROM: Requested invalid track #%u for session #%u\n", trackNum, cdCmd & 0xFF);
480 }
481 else
482 {
483 if (cdPtr < 0x62)
484 data = (cdPtr << 8) | trackNum;
485 else if (cdPtr < 0x65)
486 data = (cdPtr << 8) | CDIntfGetTrackInfo(trackNum, (cdPtr - 2) & 0x0F);
487
488WriteLog("CDROM: Reading DS_DATA (session #%u, full TOC byte #%u): $%04X\n", cdCmd & 0xFF, (cdPtr+1) & 0x0F, data);
489
490 cdPtr++;
491 if (cdPtr == 0x65)
492 cdPtr = 0x60, trackNum++;
493 }
494
495 // Note that it seems to return track info in sets of 4 (or is it 5?)
496/*
497; +0 - track # (must be non-zero)
498; +1 - absolute minutes (0..99), start of track
499; +2 - absolute seconds (0..59), start of track
500; +3 - absolute frames, (0..74), start of track
501; +4 - session # (0..99)
502; +5 - track duration minutes
503; +6 - track duration seconds
504; +7 - track duration frames
505*/
506 // Seems to be the following format: $60xx -> Track #xx
507 // $61xx -> min? (trk?)
508 // $62xx -> sec? (min?)
509 // $63xx -> frame? (sec?)
510 // $64xx -> ? (frame?)
511/* cdPtr++;
512 switch (cdPtr)
513 {
514 case 1:
515 data = 0x6000 | trackNum; // Track #
516 break;
517 case 2:
518 data = 0x6100 | trackNum; // Track # (again?)
519 break;
520 case 3:
521 data = 0x6200 | minutes[trackNum]; // Minutes
522 break;
523 case 4:
524 data = 0x6300 | seconds[trackNum]; // Seconds
525 break;
526 case 5:
527 data = 0x6400 | frames[trackNum]; // Frames
528 trackNum++;
529 cdPtr = 0;
530 }//*/
531 }
532 else if ((cdCmd & 0xFF00) == 0x1500) // Read CD mode
533 {
534 data = cdCmd | 0x0200; // ?? not sure ?? [Seems OK]
535 WriteLog("CDROM: Reading DS_DATA (mode), cdCmd=$%04X\n", cdCmd);
536 }
537 else if ((cdCmd & 0xFF00) == 0x1800) // Spin up session #
538 {
539 data = cdCmd;
540 WriteLog("CDROM: Reading DS_DATA (spin up session), cdCmd=$%04X\n", cdCmd);
541 }
542 else if ((cdCmd & 0xFF00) == 0x5400) // Read # of sessions
543 {
544 data = cdCmd | 0x00; // !!! Hardcoded !!! FIX !!!
545 WriteLog("CDROM: Reading DS_DATA (# of sessions), cdCmd=$%04X\n", cdCmd);
546 }
547 else if ((cdCmd & 0xFF00) == 0x7000) // Read oversampling
548 {
549//NOTE: This setting will probably affect the # of DSP interrupts that need to happen. !!! FIX !!!
550 data = cdCmd;
551 WriteLog("CDROM: Reading DS_DATA (oversampling), cdCmd=$%04X\n", cdCmd);
552 }
553 else
554 {
555 data = 0x0400;
556 WriteLog("CDROM: Reading DS_DATA, unhandled cdCmd=$%04X\n", cdCmd);
557 }
558 }
559 else if (offset == DS_DATA && !haveCDGoodness)
560 data = 0x0400; // No CD interface present, so return error
561 else if (offset >= FIFO_DATA && offset <= FIFO_DATA + 3)
562 {
563 }
564 else if (offset >= FIFO_DATA + 4 && offset <= FIFO_DATA + 7)
565 {
566 }
567 else
568 data = GET16(cdRam, offset);
569
570//Returning $00000008 seems to cause it to use the starfield. Dunno why.
571// It looks like it's getting the CD_mode this way...
572//Temp, for testing...
573//Very interesting...! Seems to control sumthin' or other...
574/*if (offset == 0x2C || offset == 0x2E)
575 data = 0xFFFF;//*/
576/*if (offset == 0x2C)
577 data = 0x0000;
578if (offset == 0x2E)
579 data = 0;//0x0008;//*/
580 if (offset == UNKNOWN + 2)
581 data = CDROMBusRead();
582
583#ifdef CDROM_LOG
584 if ((offset & 0xFF) < 11 * 4)
585 WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]);
586 if (offset != UNKNOWN && offset != UNKNOWN + 2)
587 WriteLog("CDROM: %s reading word $%04X from $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
588#endif
589 return data;
590}
591
592void CDROMWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
593{
594 offset &= 0xFF;
595 cdRam[offset] = data;
596
597#ifdef CDROM_LOG
598 if ((offset & 0xFF) < 12 * 4)
599 WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]);
600 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
601#endif
602}
603
604void CDROMWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
605{
606 offset &= 0xFF;
607 SET16(cdRam, offset, data);
608
609 // Command register
610//Lesse what this does... Seems to work OK...!
611 if (offset == DS_DATA)
612 {
613 cdCmd = data;
614 if ((data & 0xFF00) == 0x0200) // Stop CD
615 {
616 cdPtr = 0;
617 WriteLog("CDROM: Stopping CD\n", data & 0xFF);
618 }
619 else if ((data & 0xFF00) == 0x0300) // Read session TOC (short? overview?)
620 {
621 cdPtr = 0;
622 WriteLog("CDROM: Reading TOC for session #%u\n", data & 0xFF);
623 }
624//Not sure how these three acknowledge...
625 else if ((data & 0xFF00) == 0x1000) // Seek to minute position
626 {
627 min = data & 0x00FF;
628 }
629 else if ((data & 0xFF00) == 0x1100) // Seek to second position
630 {
631 sec = data & 0x00FF;
632 }
633 else if ((data & 0xFF00) == 0x1200) // Seek to frame position
634 {
635 frm = data & 0x00FF;
636 block = (((min * 60) + sec) * 75) + frm;
637 cdBufPtr = 2352; // Ensure that SSI read will do so immediately
638 WriteLog("CDROM: Seeking to %u:%02u:%02u [block #%u]\n", min, sec, frm, block);
639 }
640 else if ((data & 0xFF00) == 0x1400) // Read "full" TOC for session
641 {
642 cdPtr = 0x60,
643 minTrack = CDIntfGetSessionInfo(data & 0xFF, 0),
644 maxTrack = CDIntfGetSessionInfo(data & 0xFF, 1);
645 trackNum = minTrack;
646 WriteLog("CDROM: Reading \"full\" TOC for session #%u (min=%u, max=%u)\n", data & 0xFF, minTrack, maxTrack);
647 }
648 else if ((data & 0xFF00) == 0x1500) // Set CDROM mode
649 {
650 // Mode setting is as follows: bit 0 set -> single speed, bit 1 set -> double,
651 // bit 3 set -> multisession CD, bit 3 unset -> audio CD
652 WriteLog("CDROM: Setting mode $%02X\n", data & 0xFF);
653 }
654 else if ((data & 0xFF00) == 0x1800) // Spin up session #
655 {
656 WriteLog("CDROM: Spinning up session #%u\n", data & 0xFF);
657 }
658 else if ((data & 0xFF00) == 0x5400) // Read # of sessions
659 {
660 WriteLog("CDROM: Reading # of sessions\n", data & 0xFF);
661 }
662 else if ((data & 0xFF00) == 0x7000) // Set oversampling rate
663 {
664 // 1 = none, 2 = 2x, 3 = 4x, 4 = 8x
665 uint32_t rates[5] = { 0, 1, 2, 4, 8 };
666 WriteLog("CDROM: Setting oversample rate to %uX\n", rates[(data & 0xFF)]);
667 }
668 else
669 WriteLog("CDROM: Unknown command $%04X\n", data);
670 }//*/
671
672 if (offset == UNKNOWN + 2)
673 CDROMBusWrite(data);
674
675#ifdef CDROM_LOG
676 if ((offset & 0xFF) < 11 * 4)
677 WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]);
678 if (offset != UNKNOWN && offset != UNKNOWN + 2)
679 WriteLog("CDROM: %s writing word $%04X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
680#endif
681}
682
683//
684// State machine for sending/receiving data along a serial bus
685//
686
687enum ButchState { ST_INIT, ST_RISING, ST_FALLING };
688static ButchState currentState = ST_INIT;
689static uint16_t counter = 0;
690static bool cmdTx = false;
691static uint16_t busCmd;
692static uint16_t rxData, txData;
693static uint16_t rxDataBit;
694static bool firstTime = false;
695
696static void CDROMBusWrite(uint16_t data)
697{
698//This is kinda lame. What we should do is check for a 0->1 transition on either bits 0 or 1...
699//!!! FIX !!!
700
701#ifdef CDROM_LOG
702 if (data & 0xFFF0)
703 WriteLog("CDROM: BusWrite write on unknown line: $%04X\n", data);
704#endif
705
706 switch (currentState)
707 {
708 case ST_INIT:
709 currentState = ST_RISING;
710 break;
711 case ST_RISING:
712 if (data & 0x0001) // Command coming
713 {
714 cmdTx = true;
715 counter = 0;
716 busCmd = 0;
717 }
718 else
719 {
720 if (cmdTx)
721 {
722 busCmd <<= 1; // Make room for next bit
723 busCmd |= (data & 0x04); // & put it in
724 counter++;
725
726 if (counter == 9)
727 {
728 busCmd >>= 2; // Because we ORed bit 2, we need to shift right by 2
729 cmdTx = false;
730
731//What it looks like:
732//It seems that the $18x series reads from NVRAM while the
733//$130, $14x, $100 series writes values to NVRAM...
734 if (busCmd == 0x180)
735 rxData = 0x0024;//1234;
736 else if (busCmd == 0x181)
737 rxData = 0x0004;//5678;
738 else if (busCmd == 0x182)
739 rxData = 0x0071;//9ABC;
740 else if (busCmd == 0x183)
741 rxData = 0xFF67;//DEF0;
742 else if (busCmd == 0x184)
743 rxData = 0xFFFF;//892F;
744 else if (busCmd == 0x185)
745 rxData = 0xFFFF;//8000;
746 else
747 rxData = 0x0001;
748// rxData = 0x8349;//8000;//0F67;
749
750 counter = 0;
751 firstTime = true;
752 txData = 0;
753#ifdef CDROM_LOG
754 WriteLog("CDROM: *** BusWrite got command $%04X\n", busCmd);
755#endif
756 }
757 }
758 else
759 {
760 txData = (txData << 1) | ((data & 0x04) >> 2);
761//WriteLog("[%s]", data & 0x04 ? "1" : "0");
762
763 rxDataBit = (rxData & 0x8000) >> 12;
764 rxData <<= 1;
765 counter++;
766#ifdef CDROM_LOG
767 if (counter == 16)
768 WriteLog("CDROM: *** BusWrite got extra command $%04X\n", txData);
769#endif
770 }
771 }
772
773 currentState = ST_FALLING;
774 break;
775 case ST_FALLING:
776 currentState = ST_INIT;
777 break;
778 }
779}
780
781static uint16_t CDROMBusRead(void)
782{
783// It seems the counter == 0 simply waits for a single bit acknowledge-- !!! FIX !!!
784// Or does it? Hmm. It still "pumps" 16 bits through above, so how is this special?
785// Seems to be because it sits and looks at it as if it will change. Dunno!
786#ifdef CDROM_LOG
787 if ((counter & 0x0F) == 0)
788 {
789 if (counter == 0 && rxDataBit == 0)
790 {
791 if (firstTime)
792 {
793 firstTime = false;
794 WriteLog("0...\n");
795 }
796 }
797 else
798 WriteLog("%s\n", rxDataBit ? "1" : "0");
799 }
800 else
801 WriteLog("%s", rxDataBit ? "1" : "0");
802#endif
803
804 return rxDataBit;
805}
806
807//
808// This simulates a read from BUTCH over the SSI to JERRY. Uses real reading!
809//
810//temp, until I can fix my CD image... Argh!
811static uint8_t cdBuf2[2532 + 96], cdBuf3[2532 + 96];
812uint16_t GetWordFromButchSSI(uint32_t offset, uint32_t who/*= UNKNOWN*/)
813{
814 bool go = ((offset & 0x0F) == 0x0A || (offset & 0x0F) == 0x0E ? true : false);
815
816 if (!go)
817 return 0x000;
818
819// The problem comes in here. Really, we should generate the IRQ once we've stuffed
820// our values into the DAC L/RRXD ports...
821// But then again, the whole IRQ system needs an overhaul in order to make it more
822// cycle accurate WRT to the various CPUs. Right now, it's catch-as-catch-can, which
823// means that IRQs get serviced on scanline boundaries instead of when they occur.
824 cdBufPtr += 2;
825
826 if (cdBufPtr >= 2352)
827 {
828WriteLog("CDROM: %s reading block #%u...\n", whoName[who], block);
829 //No error checking. !!! FIX !!!
830//NOTE: We have to subtract out the 1st track start as well (in cdintf_foo.cpp)!
831// CDIntfReadBlock(block - 150, cdBuf);
832
833//Crappy kludge for shitty shit. Lesse if it works!
834 CDIntfReadBlock(block - 150, cdBuf2);
835 CDIntfReadBlock(block - 149, cdBuf3);
836 for(int i=0; i<2352-4; i+=4)
837 {
838 cdBuf[i+0] = cdBuf2[i+4];
839 cdBuf[i+1] = cdBuf2[i+5];
840 cdBuf[i+2] = cdBuf2[i+2];
841 cdBuf[i+3] = cdBuf2[i+3];
842 }
843 cdBuf[2348] = cdBuf3[0];
844 cdBuf[2349] = cdBuf3[1];
845 cdBuf[2350] = cdBuf2[2350];
846 cdBuf[2351] = cdBuf2[2351];//*/
847
848 block++, cdBufPtr = 0;
849 }
850
851/*extern bool doDSPDis;
852if (block == 244968)
853 doDSPDis = true;//*/
854
855WriteLog("[%04X:%01X]", GET16(cdBuf, cdBufPtr), offset & 0x0F);
856if (cdBufPtr % 32 == 30)
857 WriteLog("\n");
858
859// return GET16(cdBuf, cdBufPtr);
860//This probably isn't endian safe...
861// But then again... It seems that even though the data on the CD is organized as
862// LL LH RL RH the way it expects to see the data is RH RL LH LL.
863// D'oh! It doesn't matter *how* the data comes in, since it puts each sample into
864// its own left or right side queue, i.e. it reads them 32 bits at a time and puts
865// them into their L/R channel queues. It does seem, though, that it expects the
866// right channel to be the upper 16 bits and the left to be the lower 16.
867 return (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0];
868}
869
870bool ButchIsReadyToSend(void)
871{
872#ifdef LOG_CDROM_VERBOSE
873WriteLog("Butch is%s ready to send...\n", cdRam[I2CNTRL + 3] & 0x02 ? "" : " not");
874#endif
875 return (cdRam[I2CNTRL + 3] & 0x02 ? true : false);
876}
877
878//
879// This simulates a read from BUTCH over the SSI to JERRY. Uses real reading!
880//
881void SetSSIWordsXmittedFromButch(void)
882{
883
884// The problem comes in here. Really, we should generate the IRQ once we've stuffed
885// our values into the DAC L/RRXD ports...
886// But then again, the whole IRQ system needs an overhaul in order to make it more
887// cycle accurate WRT to the various CPUs. Right now, it's catch-as-catch-can, which
888// means that IRQs get serviced on scanline boundaries instead of when they occur.
889
890// NOTE: The CD BIOS uses the following SMODE:
891// DAC: M68K writing to SMODE. Bits: WSEN FALLING [68K PC=00050D8C]
892 cdBufPtr += 4;
893
894 if (cdBufPtr >= 2352)
895 {
896WriteLog("CDROM: Reading block #%u...\n", block);
897 //No error checking. !!! FIX !!!
898//NOTE: We have to subtract out the 1st track start as well (in cdintf_foo.cpp)!
899// CDIntfReadBlock(block - 150, cdBuf);
900
901//Crappy kludge for shitty shit. Lesse if it works!
902//It does! That means my CD is WRONG! FUCK!
903
904// But, then again, according to Belboz at AA the two zeroes in front *ARE* necessary...
905// So that means my CD is OK, just this method is wrong!
906// It all depends on whether or not the interrupt occurs on the RISING or FALLING edge
907// of the word strobe... !!! FIX !!!
908
909// When WS rises, left channel was done transmitting. When WS falls, right channel is done.
910// CDIntfReadBlock(block - 150, cdBuf2);
911// CDIntfReadBlock(block - 149, cdBuf3);
912 CDIntfReadBlock(block, cdBuf2);
913 CDIntfReadBlock(block + 1, cdBuf3);
914 memcpy(cdBuf, cdBuf2 + 2, 2350);
915 cdBuf[2350] = cdBuf3[0];
916 cdBuf[2351] = cdBuf3[1];//*/
917
918 block++, cdBufPtr = 0;
919
920/*extern bool doDSPDis;
921static int foo = 0;
922if (block == 244968)
923{
924 foo++;
925WriteLog("\n***** foo = %u, block = %u *****\n\n", foo, block);
926 if (foo == 2)
927 doDSPDis = true;
928}//*/
929 }
930
931
932WriteLog("[%02X%02X %02X%02X]", cdBuf[cdBufPtr+1], cdBuf[cdBufPtr+0], cdBuf[cdBufPtr+3], cdBuf[cdBufPtr+2]);
933if (cdBufPtr % 32 == 28)
934 WriteLog("\n");
935
936//This probably isn't endian safe...
937// But then again... It seems that even though the data on the CD is organized as
938// LL LH RL RH the way it expects to see the data is RH RL LH LL.
939// D'oh! It doesn't matter *how* the data comes in, since it puts each sample into
940// its own left or right side queue, i.e. it reads them 32 bits at a time and puts
941// them into their L/R channel queues. It does seem, though, that it expects the
942// right channel to be the upper 16 bits and the left to be the lower 16.
943
944// This behavior is strictly a function of *where* the WS creates an IRQ. If the data
945// is shifted by two zeroes (00 00 in front of the data file) then this *is* the
946// correct behavior, since the left channel will be xmitted followed by the right
947
948// Now we have definitive proof: The MYST CD shows a word offset. So that means we have
949// to figure out how to make that work here *without* having to load 2 sectors, offset, etc.
950// !!! FIX !!!
951 lrxd = (cdBuf[cdBufPtr + 3] << 8) | cdBuf[cdBufPtr + 2],
952 rrxd = (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0];
953}
954
955/*
956[18667]
957TOC for MYST
958
959CDINTF: Disc summary
960 # of sessions: 2, # of tracks: 10
961 Session info:
962 1: min track= 1, max track= 1, lead out= 1:36:67
963 2: min track= 2, max track=10, lead out=55:24:71
964 Track info:
965 1: start= 0:02:00
966 2: start= 4:08:67
967 3: start= 4:16:65
968 4: start= 4:29:19
969 5: start=29:31:03
970 6: start=33:38:50
971 7: start=41:38:60
972 8: start=44:52:18
973 9: start=51:51:22
974 10: start=55:18:73
975
976CDROM: Read sector 18517 (18667 - 150)...
977
9780000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9790018: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9800030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9810048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9820060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9830078: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9840090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
98500A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
98600C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
98700D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
98800F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9890108: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9900120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9910138: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9920150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9930168: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9940180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9950198: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
99601B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
99701C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
99801E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
99901F8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10010228: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10020240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10030258: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10040270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10050288: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100602A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100702B8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100802D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100902E8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10100300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10110318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10120330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10130348: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10140360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10150378: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10160390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
101703A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
101803C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
101903D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
102003F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10210408: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10220420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10230438: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10240450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10250468: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10260480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10270498: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
102804B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
102904C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
103004E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
103104F8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10320510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10330528: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10340540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10350558: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10360570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10370588: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
103805A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
103905B8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
104005D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
104105E8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10420600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10430618: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10440630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10450648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10460660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10470678: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10480690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
104906A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
105006C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
105106D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
105206F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10530708: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10540720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10550738: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10560750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10570768: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10580780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10590798: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
106007B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
106107C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[54 41 49 52]54 41
106207E0: 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41
106307F8: 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41
10640810: 49 52 54 41 49 52[54 41 49 52]54 41 52 41 20 49 50 41 52 50 56 4F 44 45
10650828: 44 20 54 41 20 41 45 48 44 41 52 45 41 20 52 54 20 49[00 00 00 50]01 00
10660840: 80 83 FC 23 07 00 07 00 F0 00 0C 21 FC 23 07 00 07 00 F1 00 0C A1 FC 33
10670858: FF FF F0 00 4E 00 7C 2E 1F 00 FC FF 00 61 08 00 F9 4E 00 00 00 51 E7 48
10680870: 00 FE 39 30 F1 00 02 40 40 02 10 00 00 67 1C 00 79 42 01 00 8C D3 3C 34
10690888: 37 03 3C 30 81 05 3C 3C 0A 01 3C 38 F1 00 00 60 1A 00 FC 33 01 00 01 00
107008A0: 8C D3 3C 34 4B 03 3C 30 65 05 3C 3C 42 01 3C 38 1F 01 C0 33 01 00 88 D3
107108B8: C4 33 01 00 8A D3 00 32 41 E2 41 94 7C D4 04 00 7C 92 01 00 41 00 00 04
107208D0: C1 33 01 00 82 D3 C1 33 F0 00 3C 00 C2 33 01 00 80 D3 C2 33 F0 00 38 00
107308E8: C2 33 F0 00 3A 00 06 3A 44 9A C5 33 01 00 84 D3 44 DC C6 33 01 00 86 D3
10740900: F9 33 01 00 84 D3 F0 00 46 00 FC 33 FF FF F0 00 48 00 FC 23 00 00 00 00
10750918: F0 00 2A 00 FC 33 00 00 F0 00 58 00 DF 4C 7F 00 75 4E 00 00 00 00 00 00
1076
1077Raw P-W subchannel data:
1078
107900: 80 80 C0 80 80 80 80 C0 80 80 80 80 80 80 C0 80
108010: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
108120: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 C0
108230: 80 80 80 80 80 80 80 80 80 80 80 80 80 C0 80 80
108340: 80 80 80 80 C0 80 80 80 80 C0 C0 80 80 C0 C0 80
108450: C0 80 80 C0 C0 C0 80 80 C0 80 80 80 C0 80 80 80
1085
1086P subchannel data: FF FF FF FF FF FF FF FF FF FF FF FF
1087Q subchannel data: 21 02 00 00 00 01 00 04 08 66 9C 88
1088
1089Run address: $5000, Length: $18380
1090*/
1091
1092
1093/*
1094CD_read function from the CD BIOS: Note that it seems to direct the EXT1 interrupt
1095to the GPU--so that would mean *any* interrupt that BUTCH generates would be routed
1096to the GPU...
1097
1098read:
1099 btst.l #31,d0
1100 bne.w .play
1101 subq.l #4,a0 ; Make up for ISR pre-increment
1102 move.l d0,-(sp)
1103 move.l BUTCH,d0
1104 and.l #$ffff0000,d0
1105 move.l d0,BUTCH ; NO INTERRUPTS!!!!!!!!!!!
1106 move.l (sp)+,d0
1107; move.l #0,BUTCH
1108
1109 move.w #$101,J_INT
1110
1111 move.l d1,-(sp)
1112 move.l I2CNTRL,d1 ;Read I2S Control Register
1113 bclr #2,d1 ; Stop data
1114 move.l d1,I2CNTRL
1115 move.l (sp)+,d1
1116
1117 move.l PTRLOC,a2
1118 move.l a0,(a2)+
1119 move.l a1,(a2)+
1120 move.l #0,(a2)+
1121
1122 btst.b #7,INITTYPE
1123 beq .not_bad
1124 move.l PTRLOC,a0
1125 asl.l #5,d2
1126
1127 move.l d2,-(sp)
1128
1129 or.l #$089a3c1a,d2 ; These instructions include the bclr
1130 move.l d2,188(a0)
1131
1132 move.l (sp)+,d2
1133
1134 swap d2
1135 or.l #$3c1a1838,d2 ; These instructions include the bclr
1136 move.l d2,196(a0)
1137
1138 move.l #16,(a2)+
1139 move.l d1,(a2)
1140
1141.not_bad:
1142
1143 move.w DS_DATA,d1 ; Clear any pending DSARX states
1144 move.l I2CNTRL,d1 ; Clear any pending errors
1145
1146; Drain the FIFO so that we don't get overloaded
1147
1148.dump:
1149 move.l FIFO_DATA,d1
1150 move.l I2CNTRL,d1
1151 btst #4,d1
1152 bne.b .dump
1153
1154.butch_go:
1155 move.l BUTCH,d1
1156 and.l #$FFFF0000,d1
1157 or.l #%000100001,d1 ;Enable DSARX interrupt
1158 move.l d1,BUTCH
1159; move.l #%000100001,BUTCH ;Enable DSARX interrupt
1160
1161; Do a play @
1162
1163.play: move.l d0,d1 ; mess with copy in d1
1164 lsr.l #8,d1 ; shift the byte over
1165 lsr.w #8,d1
1166 or.w #$1000,d1 ; format it for goto
1167 move.w d1,DS_DATA ; DSA tx
1168 bsr.b DSA_tx
1169
1170 move.l d0,d1 ; mess with copy in d1
1171 lsr.w #8,d1
1172 or.w #$1100,d1 ; format it for goto
1173 move.w d1,DS_DATA ; DSA tx
1174 bsr.b DSA_tx
1175
1176 move.l d0,d1 ; mess with copy in d1
1177 and.w #$00FF,d1 ; mask for minutes
1178 or.w #$1200,d1 ; format it for goto
1179 move.w d1,DS_DATA ; DSA tx
1180 bsr.b DSA_tx
1181
1182 rts
1183
1184
1185****************************
1186* Here's the GPU interrupt *
1187****************************
1188
1189JERRY_ISR:
1190 movei #G_FLAGS,r30
1191 load (r30),r29 ;read the flags
1192
1193 movei #BUTCH,r24
1194
1195make_ptr:
1196 move pc,Ptrloc
1197 movei #(make_ptr-PTRPOS),TEMP
1198 sub TEMP,Ptrloc
1199
1200HERE:
1201 move pc,r25
1202 movei #(EXIT_ISR-HERE),r27
1203 add r27,r25
1204
1205; Is this a DSARX interrupt?
1206
1207 load (r24),r27 ;check for DSARX int pending
1208 btst #13,r27
1209 jr z,fifo_read ; This should ALWAYS fall thru the first time
1210
1211; Set the match bit, to allow data
1212; moveq #3,r26 ; enable FIFO only
1213; Don't just jam a value
1214; Clear the DSARX and set FIFO
1215 bclr #5,r27
1216 bset #1,r27
1217 store r27,(r24)
1218 addq #$10,r24
1219 load (r24),r27
1220 bset #2,r27
1221 store r27,(r24) ; Disable SUBCODE match
1222
1223; Now we clear the DSARX interrupt in Butch
1224
1225 subq #12,r24 ; does what the above says
1226 load (r24),r26 ;Clears DSA pending interrupt
1227 addq #6,r24
1228 loadw (r24),r27 ; Read DSA response
1229 btst #10,r27 ; Check for error
1230 jr nz,error
1231 or r26,r26
1232 jump (r25)
1233; nop
1234
1235fifo_read:
1236; Check for ERROR!!!!!!!!!!!!!!!!!!!!!
1237 btst #14,r27
1238 jr z,noerror
1239 bset #31,r27
1240error:
1241 addq #$10,r24
1242 load (r24),TEMP
1243 or TEMP,TEMP
1244 subq #$10,r24
1245 load (Ptrloc),TEMP
1246 addq #8,Ptrloc
1247 store TEMP,(Ptrloc)
1248 subq #8,Ptrloc
1249noerror:
1250 load (Ptrloc),Dataptr ;get pointer
1251
1252; Check to see if we should stop
1253 addq #4,Ptrloc
1254 load (Ptrloc),TEMP
1255 subq #4,Ptrloc
1256 cmp Dataptr,TEMP
1257 jr pl,notend
1258; nop
1259 bclr #0,r27
1260 store r27,(r24)
1261
1262notend:
1263 movei #FIFO_DATA,CDdata
1264 move CDdata,r25
1265 addq #4,CDdata
1266loptop:
1267 load (CDdata),TEMP
1268 load (r25),r30
1269 load (CDdata),r21
1270 load (r25),r22
1271 load (CDdata),r24
1272 load (r25),r20
1273 load (CDdata),r19
1274 load (r25),r18
1275 addq #4,Dataptr
1276 store TEMP,(Dataptr)
1277 addqt #4,Dataptr
1278 store r30,(Dataptr)
1279 addqt #4,Dataptr
1280 store r21,(Dataptr)
1281 addqt #4,Dataptr
1282 store r22,(Dataptr)
1283 addqt #4,Dataptr
1284 store r24,(Dataptr)
1285 addqt #4,Dataptr
1286 store r20,(Dataptr)
1287 addqt #4,Dataptr
1288 store r19,(Dataptr)
1289 addqt #4,Dataptr
1290 store r18,(Dataptr)
1291
1292 store Dataptr,(Ptrloc)
1293
1294exit_isr:
1295 movei #J_INT,r24 ; Acknowledge in Jerry
1296 moveq #1,TEMP
1297 bset #8,TEMP
1298 storew TEMP,(r24)
1299
1300.if FLAG
1301; Stack r18
1302 load (r31),r18
1303 addq #4,r31
1304
1305; Stack r19
1306 load (r31),r19
1307 addq #4,r31
1308
1309; Stack r20
1310 load (r31),r20
1311 addq #4,r31
1312
1313; Stack r21
1314 load (r31),r21
1315 addq #4,r31
1316
1317; Stack r22
1318 load (r31),r22
1319 addq #4,r31
1320
1321; Stack r23
1322 load (r31),r23
1323 addq #4,r31
1324
1325; Stack r26
1326 load (r31),r26
1327 addq #4,r31
1328
1329; Stack r27
1330 load (r31),r27
1331 addq #4,r31
1332
1333; Stack r24
1334 load (r31),r24
1335 addq #4,r31
1336
1337; Stack r25
1338 load (r31),r25
1339 addq #4,r31
1340.endif
1341
1342 movei #G_FLAGS,r30
1343
1344;r29 already has flags
1345 bclr #3,r29 ;IMASK
1346 bset #10,r29 ;Clear DSP int bit in TOM
1347
1348 load (r31),r28 ;Load return address
1349
1350
1351 addq #2,r28 ;Fix it up
1352 addq #4,r31
1353 jump (r28) ;Return
1354 store r29,(r30) ;Restore broken flags
1355
1356
1357 align long
1358
1359stackbot:
1360 ds.l 20
1361STACK:
1362
1363
1364*/
1365