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
9 // JLH = James Hammons <jlhamm@acm.org>
12 // --- ---------- ------------------------------------------------------------
13 // JLH 01/16/2010 Created this log ;-)
18 #include <string.h> // For memset, etc.
19 //#include "jaguar.h" // For GET32/SET32 macros
20 //#include "m68k.h" //???
22 #include "cdintf.h" // System agnostic CD interface functions
26 //#define CDROM_LOG // For CDROM logging, obviously
29 BUTCH equ $DFFF00 ; base of Butch=interrupt control register, R/W
30 DSCNTRL equ BUTCH+4 ; DSA control register, R/W
31 DS_DATA equ BUTCH+$A ; DSA TX/RX data, R/W
32 I2CNTRL equ BUTCH+$10 ; i2s bus control register, R/W
33 SBCNTRL equ BUTCH+$14 ; CD subcode control register, R/W
34 SUBDATA equ BUTCH+$18 ; Subcode data register A
35 SUBDATB equ BUTCH+$1C ; Subcode data register B
36 SB_TIME equ BUTCH+$20 ; Subcode time and compare enable (D24)
37 FIFO_DATA equ BUTCH+$24 ; i2s FIFO data
38 I2SDAT1 equ BUTCH+$24 ; i2s FIFO data
39 I2SDAT2 equ BUTCH+$28 ; i2s FIFO data
40 equ BUTCH+$2C ; CD EEPROM interface
43 ; Butch's hardware registers
45 ;BUTCH equ $DFFF00 ;base of Butch=interrupt control register, R/W
47 ; When written (Long):
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
57 ; bit7-31 reserved, set to 0
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
72 O_DSCNTRL equ 4 ; DSA control register, R/W
73 O_DS_DATA equ $A ; DSA TX/RX data, R/W
75 O_I2CNTRL equ $10 ; i2s bus control register, R/W
79 ; b0 - I2S data from drive is ON if 1
80 ; b1 - I2S path to Jerry is ON if 1
82 ; b3 - host bus width is 16 if 1, else 32
83 ; b4 - FIFO state is not empty if 1
85 O_SBCNTRL equ $14 ; CD subcode control register, R/W
86 O_SUBDATA equ $18 ; Subcode data register A
87 O_SUBDATB equ $1C ; Subcode data register B
88 O_SB_TIME equ $20 ; Subcode time and compare enable (D24)
89 O_FIFODAT equ $24 ; i2s FIFO data
90 O_I2SDAT2 equ $28 ; i2s FIFO data (old)
94 Commands sent through DS_DATA:
96 $01nn - ? Play track nn ? Seek to track nn ?
98 $03nn - Read session nn TOC (short)
104 $14nn - Read session nn TOC (full)
106 $18nn - Spin up CD to session nn
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
113 Commands send through serial bus:
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
130 ; The BUTCH interface for the CD-ROM module is a long-word register,
131 ; where only the least signifigant 4 bits are used
133 eeprom equ $DFFF2c ;interface to CD-eeprom
135 ; bit3 - busy if 0 after write cmd, or Data In after read cmd
138 ; bit0 - Chip Select (CS)
141 ; Commands specific to the National Semiconductor NM93C14
146 eREAD equ %110000000 ;read from EEPROM
147 eEWEN equ %100110000 ;Erase/write Enable
148 eERASE equ %111000000 ;Erase selected register
149 eWRITE equ %101000000 ;Write selected register
150 eERAL equ %100100000 ;Erase all registers
151 eWRAL equ %100010000 ;Writes all registers
152 eEWDS equ %100000000 ;Erase/Write disable (default)
154 So... are there $40 words of memory? 128 bytes?
158 // Private function prototypes
160 static void CDROMBusWrite(uint16_t);
161 static uint16_t CDROMBusRead(void);
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
175 const char * BReg
[12] = { "BUTCH", "DSCNTRL", "DS_DATA", "???", "I2CNTRL",
176 "SBCNTRL", "SUBDATA", "SUBDATB", "SB_TIME", "FIFO_DATA", "I2SDAT2",
178 //extern const char * whoName[9];
181 static uint8_t cdRam
[0x100];
182 static uint16_t cdCmd
= 0, cdPtr
= 0;
183 static bool haveCDGoodness
;
184 static uint32_t min
, sec
, frm
, block
;
185 static uint8_t cdBuf
[2352 + 96];
186 static uint32_t cdBufPtr
= 2352;
187 //Also need to set up (save/restore) the CD's NVRAM
190 //extern bool GetRawTOC(void);
193 haveCDGoodness
= CDIntfInit();
197 uint32_t sec = 18667 - 150;
198 memset(buf, 0, 2448);
199 if (!CDIntfReadBlock(sec, buf))
201 WriteLog("CDROM: Attempt to read with subchannel data failed!\n");
207 WriteLog("\nCDROM: Read sector %u...\n\n", sec);
208 for(int i=0; i<98; i++)
210 WriteLog("%04X: ", i*24);
211 for(int j=0; j<24; j++)
213 WriteLog("%02X ", buf[j + (i*24)]);
217 WriteLog("\nRaw P-W subchannel data:\n\n");
218 for(int i=0; i<6; i++)
220 WriteLog("%02X: ", i*16);
221 for(int j=0; j<16; j++)
223 WriteLog("%02X ", buf[2352 + j + (i*16)]);
227 WriteLog("\nP subchannel data: ");
228 for(int i=0; i<96; i+=8)
231 for(int j=0; j<8; j++)
232 b |= ((buf[2352 + i + j] & 0x80) >> 7) << (7 - j);
234 WriteLog("%02X ", b);
236 WriteLog("\nQ subchannel data: ");
237 for(int i=0; i<96; i+=8)
240 for(int j=0; j<8; j++)
241 b |= ((buf[2352 + i + j] & 0x40) >> 6) << (7 - j);
243 WriteLog("%02X ", b);
245 WriteLog("\n\n");//*/
248 void CDROMReset(void)
250 memset(cdRam
, 0x00, 0x100);
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.
266 void BUTCHExec(uint32_t cycles
)
269 // We're chickening out for now...
272 // extern uint8_t * jerry_ram_8; // Hmm.
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
);
277 if (!(cdState
& 0x01)) // No BUTCH interrupts enabled
280 if (!(cdState
& 0x22))
281 return; // For now, we only handle FIFO/buffer full interrupts...
283 // From what I can make out, it seems that each FIFO is 32 bytes long
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
);
294 // CD-ROM memory access functions
297 uint8_t CDROMReadByte(uint32_t offset
, uint32_t who
/*=UNKNOWN*/)
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
));
304 return cdRam
[offset
& 0xFF];
307 static 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;
312 uint16_t CDROMReadWord(uint32_t offset
, uint32_t who
/*=UNKNOWN*/)
316 uint16_t 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.
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
)
335 if ((cdCmd
& 0xFF00) == 0x0100) // ???
337 //Not sure how to acknowledge the ???...
338 // data = 0x0400;//?? 0x0200;
357 WriteLog("CDROM: Reading DS_DATA (???), cdCmd=$%04X\n", cdCmd
);
359 else if ((cdCmd
& 0xFF00) == 0x0200) // Stop CD
361 //Not sure how to acknowledge the stop...
362 data
= 0x0400;//?? 0x0200;
381 WriteLog("CDROM: Reading DS_DATA (stop), cdCmd=$%04X\n", cdCmd
);
383 else if ((cdCmd
& 0xFF00) == 0x0300) // Read session TOC (overview?)
387 TOC: [Sess] [adrCtl] [?] [point] [?] [?] [?] [?] [pmin] [psec] [pframe]
388 TOC: 1 10 00 a0 00:00:00 00 01:00:00
389 TOC: 1 10 00 a1 00:00:00 00 01:00:00
390 TOC: 1 10 00 a2 00:00:00 00 03:42:42
391 TOC: 1 10 00 1 00:00:00 00 00:02:00 <-- Track #1
392 TOC: 1 50 00 b0 06:12:42 02 79:59:74
393 TOC: 1 50 00 c0 128:00:32 00 97:18:06
394 TOC: 2 10 00 a0 00:00:00 00 02:00:00
395 TOC: 2 10 00 a1 00:00:00 00 11:00:00
396 TOC: 2 10 00 a2 00:00:00 00 54:32:18
397 TOC: 2 10 00 2 00:00:00 00 06:14:42 <-- Track #2
398 TOC: 2 10 00 3 00:00:00 00 06:24:42 <-- Track #3
399 TOC: 2 10 00 4 00:00:00 00 17:42:00 <-- Track #4
400 TOC: 2 10 00 5 00:00:00 00 22:26:15 <-- Track #5
401 TOC: 2 10 00 6 00:00:00 00 29:50:16 <-- Track #6
402 TOC: 2 10 00 7 00:00:00 00 36:01:49 <-- Track #7
403 TOC: 2 10 00 8 00:00:00 00 40:37:59 <-- Track #8
404 TOC: 2 10 00 9 00:00:00 00 45:13:70 <-- Track #9
405 TOC: 2 10 00 a 00:00:00 00 49:50:06 <-- Track #10
406 TOC: 2 10 00 b 00:00:00 00 54:26:17 <-- Track #11
409 //Should do something like so:
410 // data = GetSessionInfo(cdCmd & 0xFF, cdPtr);
411 data
= CDIntfGetSessionInfo(cdCmd
& 0xFF, cdPtr
);
412 if (data
== 0xFF) // Failed...
415 WriteLog("CDROM: Requested invalid session #%u (or failed to load TOC, or bad cdPtr value)\n", cdCmd
& 0xFF);
419 data
|= (0x20 | cdPtr
++) << 8;
420 WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd
& 0xFF, cdPtr
, data
);
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?)
431 data = 0x2001; // Min track for this session?
434 data = 0x210A; // Max track for this session?
437 data = 0x2219; // Max lead-out time, absolute minutes
440 data = 0x2319; // Max lead-out time, absolute seconds
443 data = 0x2419; // Max lead-out time, absolute frames
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
458 WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd & 0xFF, cdPtr, data);
463 WriteLog("CDROM: Requested invalid session #%u\n", cdCmd & 0xFF);
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
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]
476 if (trackNum
> maxTrack
)
479 WriteLog("CDROM: Requested invalid track #%u for session #%u\n", trackNum
, cdCmd
& 0xFF);
484 data
= (cdPtr
<< 8) | trackNum
;
485 else if (cdPtr
< 0x65)
486 data
= (cdPtr
<< 8) | CDIntfGetTrackInfo(trackNum
, (cdPtr
- 2) & 0x0F);
488 WriteLog("CDROM: Reading DS_DATA (session #%u, full TOC byte #%u): $%04X\n", cdCmd
& 0xFF, (cdPtr
+1) & 0x0F, data
);
492 cdPtr
= 0x60, trackNum
++;
495 // Note that it seems to return track info in sets of 4 (or is it 5?)
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
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?)
515 data = 0x6000 | trackNum; // Track #
518 data = 0x6100 | trackNum; // Track # (again?)
521 data = 0x6200 | minutes[trackNum]; // Minutes
524 data = 0x6300 | seconds[trackNum]; // Seconds
527 data = 0x6400 | frames[trackNum]; // Frames
532 else if ((cdCmd
& 0xFF00) == 0x1500) // Read CD mode
534 data
= cdCmd
| 0x0200; // ?? not sure ?? [Seems OK]
535 WriteLog("CDROM: Reading DS_DATA (mode), cdCmd=$%04X\n", cdCmd
);
537 else if ((cdCmd
& 0xFF00) == 0x1800) // Spin up session #
540 WriteLog("CDROM: Reading DS_DATA (spin up session), cdCmd=$%04X\n", cdCmd
);
542 else if ((cdCmd
& 0xFF00) == 0x5400) // Read # of sessions
544 data
= cdCmd
| 0x00; // !!! Hardcoded !!! FIX !!!
545 WriteLog("CDROM: Reading DS_DATA (# of sessions), cdCmd=$%04X\n", cdCmd
);
547 else if ((cdCmd
& 0xFF00) == 0x7000) // Read oversampling
549 //NOTE: This setting will probably affect the # of DSP interrupts that need to happen. !!! FIX !!!
551 WriteLog("CDROM: Reading DS_DATA (oversampling), cdCmd=$%04X\n", cdCmd
);
556 WriteLog("CDROM: Reading DS_DATA, unhandled cdCmd=$%04X\n", cdCmd
);
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)
564 else if (offset
>= FIFO_DATA
+ 4 && offset
<= FIFO_DATA
+ 7)
568 data
= GET16(cdRam
, offset
);
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)
576 /*if (offset == 0x2C)
579 data = 0;//0x0008;//*/
580 if (offset
== UNKNOWN
+ 2)
581 data
= CDROMBusRead();
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
));
592 void CDROMWriteByte(uint32_t offset
, uint8_t data
, uint32_t who
/*=UNKNOWN*/)
595 cdRam
[offset
] = data
;
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
));
604 void CDROMWriteWord(uint32_t offset
, uint16_t data
, uint32_t who
/*=UNKNOWN*/)
607 SET16(cdRam
, offset
, data
);
610 //Lesse what this does... Seems to work OK...!
611 if (offset
== DS_DATA
)
614 if ((data
& 0xFF00) == 0x0200) // Stop CD
617 WriteLog("CDROM: Stopping CD\n", data
& 0xFF);
619 else if ((data
& 0xFF00) == 0x0300) // Read session TOC (short? overview?)
622 WriteLog("CDROM: Reading TOC for session #%u\n", data
& 0xFF);
624 //Not sure how these three acknowledge...
625 else if ((data
& 0xFF00) == 0x1000) // Seek to minute position
629 else if ((data
& 0xFF00) == 0x1100) // Seek to second position
633 else if ((data
& 0xFF00) == 0x1200) // Seek to frame position
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
);
640 else if ((data
& 0xFF00) == 0x1400) // Read "full" TOC for session
643 minTrack
= CDIntfGetSessionInfo(data
& 0xFF, 0),
644 maxTrack
= CDIntfGetSessionInfo(data
& 0xFF, 1);
646 WriteLog("CDROM: Reading \"full\" TOC for session #%u (min=%u, max=%u)\n", data
& 0xFF, minTrack
, maxTrack
);
648 else if ((data
& 0xFF00) == 0x1500) // Set CDROM mode
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);
654 else if ((data
& 0xFF00) == 0x1800) // Spin up session #
656 WriteLog("CDROM: Spinning up session #%u\n", data
& 0xFF);
658 else if ((data
& 0xFF00) == 0x5400) // Read # of sessions
660 WriteLog("CDROM: Reading # of sessions\n", data
& 0xFF);
662 else if ((data
& 0xFF00) == 0x7000) // Set oversampling rate
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)]);
669 WriteLog("CDROM: Unknown command $%04X\n", data
);
672 if (offset
== UNKNOWN
+ 2)
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
));
684 // State machine for sending/receiving data along a serial bus
687 enum ButchState
{ ST_INIT
, ST_RISING
, ST_FALLING
};
688 static ButchState currentState
= ST_INIT
;
689 static uint16_t counter
= 0;
690 static bool cmdTx
= false;
691 static uint16_t busCmd
;
692 static uint16_t rxData
, txData
;
693 static uint16_t rxDataBit
;
694 static bool firstTime
= false;
696 static void CDROMBusWrite(uint16_t data
)
698 //This is kinda lame. What we should do is check for a 0->1 transition on either bits 0 or 1...
703 WriteLog("CDROM: BusWrite write on unknown line: $%04X\n", data
);
706 switch (currentState
)
709 currentState
= ST_RISING
;
712 if (data
& 0x0001) // Command coming
722 busCmd
<<= 1; // Make room for next bit
723 busCmd
|= (data
& 0x04); // & put it in
728 busCmd
>>= 2; // Because we ORed bit 2, we need to shift right by 2
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...
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;
748 // rxData = 0x8349;//8000;//0F67;
754 WriteLog("CDROM: *** BusWrite got command $%04X\n", busCmd
);
760 txData
= (txData
<< 1) | ((data
& 0x04) >> 2);
761 //WriteLog("[%s]", data & 0x04 ? "1" : "0");
763 rxDataBit
= (rxData
& 0x8000) >> 12;
768 WriteLog("CDROM: *** BusWrite got extra command $%04X\n", txData
);
773 currentState
= ST_FALLING
;
776 currentState
= ST_INIT
;
781 static uint16_t CDROMBusRead(void)
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!
787 if ((counter
& 0x0F) == 0)
789 if (counter
== 0 && rxDataBit
== 0)
798 WriteLog("%s\n", rxDataBit
? "1" : "0");
801 WriteLog("%s", rxDataBit
? "1" : "0");
808 // This simulates a read from BUTCH over the SSI to JERRY. Uses real reading!
810 //temp, until I can fix my CD image... Argh!
811 static uint8_t cdBuf2
[2532 + 96], cdBuf3
[2532 + 96];
812 uint16_t GetWordFromButchSSI(uint32_t offset
, uint32_t who
/*= UNKNOWN*/)
814 bool go
= ((offset
& 0x0F) == 0x0A || (offset
& 0x0F) == 0x0E ? true : false);
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.
826 if (cdBufPtr
>= 2352)
828 WriteLog("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);
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)
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];
843 cdBuf
[2348] = cdBuf3
[0];
844 cdBuf
[2349] = cdBuf3
[1];
845 cdBuf
[2350] = cdBuf2
[2350];
846 cdBuf
[2351] = cdBuf2
[2351];//*/
848 block
++, cdBufPtr
= 0;
851 /*extern bool doDSPDis;
855 WriteLog("[%04X:%01X]", GET16(cdBuf
, cdBufPtr
), offset
& 0x0F);
856 if (cdBufPtr
% 32 == 30)
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];
870 bool ButchIsReadyToSend(void)
872 #ifdef LOG_CDROM_VERBOSE
873 WriteLog("Butch is%s ready to send...\n", cdRam
[I2CNTRL
+ 3] & 0x02 ? "" : " not");
875 return (cdRam
[I2CNTRL
+ 3] & 0x02 ? true : false);
879 // This simulates a read from BUTCH over the SSI to JERRY. Uses real reading!
881 void SetSSIWordsXmittedFromButch(void)
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.
890 // NOTE: The CD BIOS uses the following SMODE:
891 // DAC: M68K writing to SMODE. Bits: WSEN FALLING [68K PC=00050D8C]
894 if (cdBufPtr
>= 2352)
896 WriteLog("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);
901 //Crappy kludge for shitty shit. Lesse if it works!
902 //It does! That means my CD is WRONG! FUCK!
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 !!!
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];//*/
918 block
++, cdBufPtr
= 0;
920 /*extern bool doDSPDis;
925 WriteLog("\n***** foo = %u, block = %u *****\n\n", foo, block);
932 WriteLog("[%02X%02X %02X%02X]", cdBuf
[cdBufPtr
+1], cdBuf
[cdBufPtr
+0], cdBuf
[cdBufPtr
+3], cdBuf
[cdBufPtr
+2]);
933 if (cdBufPtr
% 32 == 28)
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.
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
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.
951 lrxd
= (cdBuf
[cdBufPtr
+ 3] << 8) | cdBuf
[cdBufPtr
+ 2],
952 rrxd
= (cdBuf
[cdBufPtr
+ 1] << 8) | cdBuf
[cdBufPtr
+ 0];
960 # of sessions: 2, # of tracks: 10
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
976 CDROM: Read sector 18517 (18667 - 150)...
978 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
979 0018: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
980 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
981 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
982 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
983 0078: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
984 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
985 00A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
986 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
987 00D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
988 00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
989 0108: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
990 0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
991 0138: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
992 0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
993 0168: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
994 0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
995 0198: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
996 01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
997 01C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
998 01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
999 01F8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1000 0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1001 0228: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1002 0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1003 0258: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1004 0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1005 0288: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1006 02A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1007 02B8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1008 02D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1009 02E8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1010 0300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1011 0318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1012 0330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1013 0348: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1014 0360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1015 0378: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1016 0390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1017 03A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1018 03C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1019 03D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1020 03F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1021 0408: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1022 0420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1023 0438: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1024 0450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1025 0468: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1026 0480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1027 0498: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1028 04B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1029 04C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1030 04E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1031 04F8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1032 0510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1033 0528: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1034 0540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1035 0558: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1036 0570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1037 0588: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1038 05A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1039 05B8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1040 05D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1041 05E8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1042 0600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1043 0618: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1044 0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1045 0648: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1046 0660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1047 0678: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1048 0690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1049 06A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1050 06C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1051 06D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1052 06F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1053 0708: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1054 0720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1055 0738: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1056 0750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1057 0768: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1058 0780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1059 0798: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1060 07B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1061 07C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[54 41 49 52]54 41
1062 07E0: 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41
1063 07F8: 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41 49 52 54 41
1064 0810: 49 52 54 41 49 52[54 41 49 52]54 41 52 41 20 49 50 41 52 50 56 4F 44 45
1065 0828: 44 20 54 41 20 41 45 48 44 41 52 45 41 20 52 54 20 49[00 00 00 50]01 00
1066 0840: 80 83 FC 23 07 00 07 00 F0 00 0C 21 FC 23 07 00 07 00 F1 00 0C A1 FC 33
1067 0858: FF FF F0 00 4E 00 7C 2E 1F 00 FC FF 00 61 08 00 F9 4E 00 00 00 51 E7 48
1068 0870: 00 FE 39 30 F1 00 02 40 40 02 10 00 00 67 1C 00 79 42 01 00 8C D3 3C 34
1069 0888: 37 03 3C 30 81 05 3C 3C 0A 01 3C 38 F1 00 00 60 1A 00 FC 33 01 00 01 00
1070 08A0: 8C D3 3C 34 4B 03 3C 30 65 05 3C 3C 42 01 3C 38 1F 01 C0 33 01 00 88 D3
1071 08B8: C4 33 01 00 8A D3 00 32 41 E2 41 94 7C D4 04 00 7C 92 01 00 41 00 00 04
1072 08D0: C1 33 01 00 82 D3 C1 33 F0 00 3C 00 C2 33 01 00 80 D3 C2 33 F0 00 38 00
1073 08E8: C2 33 F0 00 3A 00 06 3A 44 9A C5 33 01 00 84 D3 44 DC C6 33 01 00 86 D3
1074 0900: F9 33 01 00 84 D3 F0 00 46 00 FC 33 FF FF F0 00 48 00 FC 23 00 00 00 00
1075 0918: F0 00 2A 00 FC 33 00 00 F0 00 58 00 DF 4C 7F 00 75 4E 00 00 00 00 00 00
1077 Raw P-W subchannel data:
1079 00: 80 80 C0 80 80 80 80 C0 80 80 80 80 80 80 C0 80
1080 10: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
1081 20: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 C0
1082 30: 80 80 80 80 80 80 80 80 80 80 80 80 80 C0 80 80
1083 40: 80 80 80 80 C0 80 80 80 80 C0 C0 80 80 C0 C0 80
1084 50: C0 80 80 C0 C0 C0 80 80 C0 80 80 80 C0 80 80 80
1086 P subchannel data: FF FF FF FF FF FF FF FF FF FF FF FF
1087 Q subchannel data: 21 02 00 00 00 01 00 04 08 66 9C 88
1089 Run address: $5000, Length: $18380
1094 CD_read function from the CD BIOS: Note that it seems to direct the EXT1 interrupt
1095 to the GPU--so that would mean *any* interrupt that BUTCH generates would be routed
1101 subq.l #4,a0 ; Make up for ISR pre-increment
1105 move.l d0,BUTCH ; NO INTERRUPTS!!!!!!!!!!!
1112 move.l I2CNTRL,d1 ;Read I2S Control Register
1113 bclr #2,d1 ; Stop data
1129 or.l #$089a3c1a,d2 ; These instructions include the bclr
1135 or.l #$3c1a1838,d2 ; These instructions include the bclr
1143 move.w DS_DATA,d1 ; Clear any pending DSARX states
1144 move.l I2CNTRL,d1 ; Clear any pending errors
1146 ; Drain the FIFO so that we don't get overloaded
1157 or.l #%000100001,d1 ;Enable DSARX interrupt
1159 ; move.l #%000100001,BUTCH ;Enable DSARX interrupt
1163 .play: move.l d0,d1 ; mess with copy in d1
1164 lsr.l #8,d1 ; shift the byte over
1166 or.w #$1000,d1 ; format it for goto
1167 move.w d1,DS_DATA ; DSA tx
1170 move.l d0,d1 ; mess with copy in d1
1172 or.w #$1100,d1 ; format it for goto
1173 move.w d1,DS_DATA ; DSA tx
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
1185 ****************************
1186 * Here's the GPU interrupt *
1187 ****************************
1191 load (r30),r29 ;read the flags
1197 movei #(make_ptr-PTRPOS),TEMP
1202 movei #(EXIT_ISR-HERE),r27
1205 ; Is this a DSARX interrupt?
1207 load (r24),r27 ;check for DSARX int pending
1209 jr z,fifo_read ; This should ALWAYS fall thru the first time
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
1221 store r27,(r24) ; Disable SUBCODE match
1223 ; Now we clear the DSARX interrupt in Butch
1225 subq #12,r24 ; does what the above says
1226 load (r24),r26 ;Clears DSA pending interrupt
1228 loadw (r24),r27 ; Read DSA response
1229 btst #10,r27 ; Check for error
1236 ; Check for ERROR!!!!!!!!!!!!!!!!!!!!!
1250 load (Ptrloc),Dataptr ;get pointer
1252 ; Check to see if we should stop
1263 movei #FIFO_DATA,CDdata
1276 store TEMP,(Dataptr)
1292 store Dataptr,(Ptrloc)
1295 movei #J_INT,r24 ; Acknowledge in Jerry
1344 ;r29 already has flags
1346 bset #10,r29 ;Clear DSP int bit in TOM
1348 load (r31),r28 ;Load return address
1351 addq #2,r28 ;Fix it up
1354 store r29,(r30) ;Restore broken flags