From 322117192376770ec14130bd8f9d404ba9cb7040 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Tue, 1 Jun 2004 19:22:05 +0000 Subject: [PATCH] Major rewrite/added BUTCH functionality --- src/cdrom.cpp | 1222 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 1166 insertions(+), 56 deletions(-) diff --git a/src/cdrom.cpp b/src/cdrom.cpp index 3b6b474..d36a159 100644 --- a/src/cdrom.cpp +++ b/src/cdrom.cpp @@ -1,15 +1,16 @@ // // CD handler // -// by David Raingeard +// Originally by David Raingeard // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) -// Cleanups/fixes by James L. Hammons +// Extensive rewrites/cleanups/fixes by James L. Hammons // +#include "jaguar.h" // For GET32/SET32 macros #include "m68k.h" +#include "cdintf.h" // System agnostic CD interface functions #include "cdrom.h" - #define CDROM_LOG // For CDROM logging, obviously /* @@ -76,29 +77,175 @@ O_SB_TIME equ $20 ; Subcode time and compare enable (D24) O_FIFODAT equ $24 ; i2s FIFO data O_I2SDAT2 equ $28 ; i2s FIFO data (old) */ -char * BReg[11] = { "BUTCH", "DSCNTRL", "DS_DATA", "I2CNTRL", "SBCNTRL", "SUBDATA", "SUBDATB", - "SB_TIME", "FIFO_DATA", "I2SDAT1", "I2SDAT2" }; + +/* +Commands sent through DS_DATA: + +$01nn - ? Play track nn ? Seek to track nn ? +$0200 - Stop CD +$03nn - Read session nn TOC (short) +$0400 - Pause CD +$0500 - Unpause CD +$10nn - Goto (min?) +$11nn - Goto (sec?) +$12nn - Goto (frm?) +$14nn - Read session nn TOC (full) +$15nn - Set CD mode +$18nn - Spin up CD to session nn +$5000 - ? +$5100 - Mute CD (audio mode only) +$51FF - Unmute CD (audio mode only) +$5400 - Read # of sessions on CD +$70nn - Set oversampling mode + +Commands send through serial bus: + +$100 - ? Acknowledge ? +$130 - ? (Seems to always prefix the $14n commands) +$140 - Returns ACK (1) (Write to NVRAM?) +$141 - Returns ACK (1) +$142 - Returns ACK (1) +$143 - Returns ACK (1) +$144 - Returns ACK (1) +$145 - Returns ACK (1) +$180 - Returns 16-bit value (NVRAM?) +$181 - Returns 16-bit value +$182 - Returns 16-bit value +$183 - Returns 16-bit value +$184 - Returns 16-bit value +$185 - Returns 16-bit value +*/ + +// Private function prototypes + +static void CDROMBusWrite(uint16); +static uint16 CDROMBusRead(void); + +#define BUTCH 0x00 // base of Butch=interrupt control register, R/W +#define DSCNTRL BUTCH + 0x04 // DSA control register, R/W +#define DS_DATA BUTCH + 0x0A // DSA TX/RX data, R/W +#define I2CNTRL BUTCH + 0x10 // i2s bus control register, R/W +#define SBCNTRL BUTCH + 0x14 // CD subcode control register, R/W +#define SUBDATA BUTCH + 0x18 // Subcode data register A +#define SUBDATB BUTCH + 0x1C // Subcode data register B +#define SB_TIME BUTCH + 0x20 // Subcode time and compare enable (D24) +#define FIFO_DATA BUTCH + 0x24 // i2s FIFO data +#define I2SDAT2 BUTCH + 0x28 // i2s FIFO data (old) +#define UNKNOWN BUTCH + 0x2C // Seems to be some sort of I2S interface + +char * BReg[12] = { "BUTCH", "DSCNTRL", "DS_DATA", "???", "I2CNTRL", "SBCNTRL", "SUBDATA", "SUBDATB", + "SB_TIME", "FIFO_DATA", "I2SDAT2", "UNKNOWN" }; extern char * whoName[9]; -static uint8 cdrom_ram[0x100]; -static uint16 cdrom_cmd = 0; +static uint8 cdRam[0x100]; +static uint16 cdCmd = 0, cdPtr = 0; +static bool haveCDGoodness; +static uint32 min, sec, frm, block; +static uint8 cdBuf[2352 + 96]; +static uint32 cdBufPtr = 2352; +//Also need to set up (save/restore) the CD's NVRAM + + +extern bool GetRawTOC(void); +void CDROMInit(void) +{ + haveCDGoodness = CDIntfInit(); + +//GetRawTOC(); +/*uint8 buf[2448]; +uint32 sec = 18667 - 150; +memset(buf, 0, 2448); +if (!CDIntfReadBlock(sec, buf)) +{ + WriteLog("CDROM: Attempt to read with subchannel data failed!\n"); + return; +} +//24x98+96 +//96=4x24=4x4x6 +WriteLog("\nCDROM: Read sector %u...\n\n", sec); +for(int i=0; i<98; i++) +{ + WriteLog("%04X: ", i*24); + for(int j=0; j<24; j++) + { + WriteLog("%02X ", buf[j + (i*24)]); + } + WriteLog("\n"); +} +WriteLog("\nRaw P-W subchannel data:\n\n"); +for(int i=0; i<6; i++) +{ + WriteLog("%02X: ", i*16); + for(int j=0; j<16; j++) + { + WriteLog("%02X ", buf[2352 + j + (i*16)]); + } + WriteLog("\n"); +} +WriteLog("\nP subchannel data: "); +for(int i=0; i<96; i+=8) +{ + uint8 b = 0; + for(int j=0; j<8; j++) + b |= ((buf[2352 + i + j] & 0x80) >> 7) << (7 - j); -void cdrom_init(void) + WriteLog("%02X ", b); +} +WriteLog("\nQ subchannel data: "); +for(int i=0; i<96; i+=8) { + uint8 b = 0; + for(int j=0; j<8; j++) + b |= ((buf[2352 + i + j] & 0x40) >> 6) << (7 - j); + + WriteLog("%02X ", b); +} +WriteLog("\n\n");//*/ } -void cdrom_reset(void) +void CDROMReset(void) { - memset(cdrom_ram, 0x00, 0x100); - cdrom_cmd = 0; + memset(cdRam, 0x00, 0x100); + cdCmd = 0; } -void cdrom_done(void) +void CDROMDone(void) { + CDIntfDone(); } + +// +// This approach is probably wrong, but let's do it for now. +// What's needed is a complete overhaul of the interrupt system so that +// interrupts are handled as they're generated--instead of the current +// scheme where they're handled on scanline boundaries. +// +void BUTCHExec(uint32 cycles) +{ +return; + extern uint8 * jerry_ram_8; // Hmm. + + // For now, we just do the FIFO interrupt. Timing is also likely to be WRONG as well. + uint32 cdState = GET32(cdRam, BUTCH); + + if (!(cdState & 0x01)) // No BUTCH interrupts enabled + return; + + if (!(cdState & 0x22)) + return; // For now, we only handle FIFO/buffer full interrupts... + + // From what I can make out, it seems that each FIFO is 32 bytes long + +// DSPSetIRQLine(DSPIRQ_EXT, ASSERT_LINE); +//I'm *sure* this is wrong--prolly need to generate DSP IRQs as well! + if (jerry_ram_8[0x23] & 0x3F) // Only generate an IRQ if enabled! + GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE); +} + + // // CD-ROM memory access functions // @@ -106,47 +253,294 @@ void cdrom_done(void) uint8 CDROMReadByte(uint32 offset, uint32 who/*=UNKNOWN*/) { #ifdef CDROM_LOG - if ((offset & 0xFF) < 11 * 4) + if ((offset & 0xFF) < 12 * 4) WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]); - WriteLog("CDROM: %s reading byte $%02X from $%08X [68K PC=$%08X]\n", whoName[who], offset, cdrom_ram[offset & 0xFF], m68k_get_reg(NULL, M68K_REG_PC)); + 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)); #endif - return cdrom_ram[offset & 0xFF]; + return cdRam[offset & 0xFF]; } +static uint8 trackNum = 1, minTrack, maxTrack; +//static uint8 minutes[16] = { 0, 0, 2, 5, 7, 10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35 }; +//static uint8 seconds[16] = { 0, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0 }; +//static uint8 frames[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +//static uint16 sd = 0; uint16 CDROMReadWord(uint32 offset, uint32 who/*=UNKNOWN*/) { offset &= 0xFF; uint16 data = 0x0000; - if (offset == 0x00) + if (offset == BUTCH) data = 0x0000; - else if (offset == 0x02) - data = 0x2000; - else if (offset == 0x0A) + else if (offset == BUTCH + 2) +// We need to fix this so it's not as brain-dead as it is now--i.e., make it so that when +// a command is sent to the CDROM, we control here whether or not it succeeded or whether +// the command is still being carried out, etc. + +// bit12 - Command to CD drive pending (trans buffer empty if 1) +// bit13 - Response from CD drive pending (rec buffer full if 1) +// data = (haveCDGoodness ? 0x3000 : 0x0000); // DSA RX Interrupt pending bit (0 = pending) +//This only returns ACKs for interrupts that are set: +//This doesn't work for the initial code that writes $180000 to BUTCH. !!! FIX !!! + data = (haveCDGoodness ? cdRam[BUTCH + 3] << 8 : 0x0000); +// else if (offset == SUBDATA + 2) +// data = sd++ | 0x0010; // Have no idea what this is... + else if (offset == DS_DATA && haveCDGoodness) { - if (cdrom_cmd == 0x7001) - data = cdrom_cmd; + if ((cdCmd & 0xFF00) == 0x0100) // ??? + { +//Not sure how to acknowledge the ???... +// data = 0x0400;//?? 0x0200; + cdPtr++; + switch (cdPtr) + { + case 1: + data = 0x0000; + break; + case 2: + data = 0x0100; + break; + case 3: + data = 0x0200; + break; + case 4: + data = 0x0300; + break; + case 5: + data = 0x0400; + }//*/ + WriteLog("CDROM: Reading DS_DATA (???), cdCmd=$%04X\n", cdCmd); + } + else if ((cdCmd & 0xFF00) == 0x0200) // Stop CD + { +//Not sure how to acknowledge the stop... + data = 0x0400;//?? 0x0200; +/* cdPtr++; + switch (cdPtr) + { + case 1: + data = 0x00FF; + break; + case 2: + data = 0x01FF; + break; + case 3: + data = 0x02FF; + break; + case 4: + data = 0x03FF; + break; + case 5: + data = 0x0400; + }//*/ + WriteLog("CDROM: Reading DS_DATA (stop), cdCmd=$%04X\n", cdCmd); + } + else if ((cdCmd & 0xFF00) == 0x0300) // Read session TOC (overview?) + { + +/* +TOC: [Sess] [adrCtl] [?] [point] [?] [?] [?] [?] [pmin] [psec] [pframe] +TOC: 1 10 00 a0 00:00:00 00 01:00:00 +TOC: 1 10 00 a1 00:00:00 00 01:00:00 +TOC: 1 10 00 a2 00:00:00 00 03:42:42 +TOC: 1 10 00 1 00:00:00 00 00:02:00 <-- Track #1 +TOC: 1 50 00 b0 06:12:42 02 79:59:74 +TOC: 1 50 00 c0 128:00:32 00 97:18:06 +TOC: 2 10 00 a0 00:00:00 00 02:00:00 +TOC: 2 10 00 a1 00:00:00 00 11:00:00 +TOC: 2 10 00 a2 00:00:00 00 54:32:18 +TOC: 2 10 00 2 00:00:00 00 06:14:42 <-- Track #2 +TOC: 2 10 00 3 00:00:00 00 06:24:42 <-- Track #3 +TOC: 2 10 00 4 00:00:00 00 17:42:00 <-- Track #4 +TOC: 2 10 00 5 00:00:00 00 22:26:15 <-- Track #5 +TOC: 2 10 00 6 00:00:00 00 29:50:16 <-- Track #6 +TOC: 2 10 00 7 00:00:00 00 36:01:49 <-- Track #7 +TOC: 2 10 00 8 00:00:00 00 40:37:59 <-- Track #8 +TOC: 2 10 00 9 00:00:00 00 45:13:70 <-- Track #9 +TOC: 2 10 00 a 00:00:00 00 49:50:06 <-- Track #10 +TOC: 2 10 00 b 00:00:00 00 54:26:17 <-- Track #11 +*/ + +//Should do something like so: +// data = GetSessionInfo(cdCmd & 0xFF, cdPtr); + data = CDIntfGetSessionInfo(cdCmd & 0xFF, cdPtr); + if (data == 0xFF) // Failed... + { + data = 0x0400; + WriteLog("CDROM: Requested invalid session #%u (or failed to load TOC, or bad cdPtr value)\n", cdCmd & 0xFF); + } + else + { + data |= (0x20 | cdPtr++) << 8; + WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd & 0xFF, cdPtr, data); + } + +/* bool isValidSession = ((cdCmd & 0xFF) == 0 ? true : false);//Hardcoded... !!! FIX !!! +//NOTE: This should return error condition if the requested session doesn't exist! ($0400?) + if (isValidSession) + { + cdPtr++; + switch (cdPtr) + { + case 1: + data = 0x2001; // Min track for this session? + break; + case 2: + data = 0x210A; // Max track for this session? + break; + case 3: + data = 0x2219; // Max lead-out time, absolute minutes + break; + case 4: + data = 0x2319; // Max lead-out time, absolute seconds + break; + case 5: + data = 0x2419; // Max lead-out time, absolute frames + break; + default: + data = 0xFFFF; + +//; +0 - unused, reserved (0) +//; +1 - unused, reserved (0) +//; +2 - minimum track number +//; +3 - maximum track number +//; +4 - total number of sessions +//; +5 - start of last lead-out time, absolute minutes +//; +6 - start of last lead-out time, absolute seconds +//; +7 - start of last lead-out time, absolute frames + + } + WriteLog("CDROM: Reading DS_DATA (session #%u TOC byte #%u): $%04X\n", cdCmd & 0xFF, cdPtr, data); + } + else + { + data = 0x0400; + WriteLog("CDROM: Requested invalid session #%u\n", cdCmd & 0xFF); + }*/ + } + // Seek to m, s, or f position + else if ((cdCmd & 0xFF00) == 0x1000 || (cdCmd & 0xFF00) == 0x1100 || (cdCmd & 0xFF00) == 0x1200) + data = 0x0100; // Success, though this doesn't take error handling into account. + // Ideally, we would also set the bits in BUTCH to let the processor know that + // this is ready to be read... !!! FIX !!! + else if ((cdCmd & 0xFF00) == 0x1400) // Read "full" session TOC + { +//Need to be a bit more tricky here, since it's reading the "session" TOC instead of the +//full TOC--so we need to check for the min/max tracks for each session here... [DONE] + + if (trackNum > maxTrack) + { + data = 0x400; +WriteLog("CDROM: Requested invalid track #%u for session #%u\n", trackNum, cdCmd & 0xFF); + } + else + { + if (cdPtr < 0x62) + data = (cdPtr << 8) | trackNum; + else if (cdPtr < 0x65) + data = (cdPtr << 8) | CDIntfGetTrackInfo(trackNum, (cdPtr - 2) & 0x0F); + +WriteLog("CDROM: Reading DS_DATA (session #%u, full TOC byte #%u): $%04X\n", cdCmd & 0xFF, (cdPtr+1) & 0x0F, data); + + cdPtr++; + if (cdPtr == 0x65) + cdPtr = 0x60, trackNum++; + } + + // Note that it seems to return track info in sets of 4 (or is it 5?) +/* +; +0 - track # (must be non-zero) +; +1 - absolute minutes (0..99), start of track +; +2 - absolute seconds (0..59), start of track +; +3 - absolute frames, (0..74), start of track +; +4 - session # (0..99) +; +5 - track duration minutes +; +6 - track duration seconds +; +7 - track duration frames +*/ + // Seems to be the following format: $60xx -> Track #xx + // $61xx -> min? (trk?) + // $62xx -> sec? (min?) + // $63xx -> frame? (sec?) + // $64xx -> ? (frame?) +/* cdPtr++; + switch (cdPtr) + { + case 1: + data = 0x6000 | trackNum; // Track # + break; + case 2: + data = 0x6100 | trackNum; // Track # (again?) + break; + case 3: + data = 0x6200 | minutes[trackNum]; // Minutes + break; + case 4: + data = 0x6300 | seconds[trackNum]; // Seconds + break; + case 5: + data = 0x6400 | frames[trackNum]; // Frames + trackNum++; + cdPtr = 0; + }//*/ + } + else if ((cdCmd & 0xFF00) == 0x1500) // Read CD mode + { + data = cdCmd | 0x0200; // ?? not sure ?? [Seems OK] + WriteLog("CDROM: Reading DS_DATA (mode), cdCmd=$%04X\n", cdCmd); + } + else if ((cdCmd & 0xFF00) == 0x1800) // Spin up session # + { + data = cdCmd; + WriteLog("CDROM: Reading DS_DATA (spin up session), cdCmd=$%04X\n", cdCmd); + } + else if ((cdCmd & 0xFF00) == 0x5400) // Read # of sessions + { + data = cdCmd | 0x00; // !!! Hardcoded !!! FIX !!! + WriteLog("CDROM: Reading DS_DATA (# of sessions), cdCmd=$%04X\n", cdCmd); + } + else if ((cdCmd & 0xFF00) == 0x7000) // Read oversampling + { +//NOTE: This setting will probably affect the # of DSP interrupts that need to happen. !!! FIX !!! + data = cdCmd; + WriteLog("CDROM: Reading DS_DATA (oversampling), cdCmd=$%04X\n", cdCmd); + } else + { data = 0x0400; + WriteLog("CDROM: Reading DS_DATA, unhandled cdCmd=$%04X\n", cdCmd); + } + } + else if (offset == DS_DATA && !haveCDGoodness) + data = 0x0400; // No CD interface present, so return error + else if (offset >= FIFO_DATA && offset <= FIFO_DATA + 3) + { + } + else if (offset >= FIFO_DATA + 4 && offset <= FIFO_DATA + 7) + { } else - data = (cdrom_ram[offset+0] << 8) | cdrom_ram[offset+1]; + data = GET16(cdRam, offset); //Returning $00000008 seems to cause it to use the starfield. Dunno why. +// It looks like it's getting the CD_mode this way... //Temp, for testing... //Very interesting...! Seems to control sumthin' or other... /*if (offset == 0x2C || offset == 0x2E) data = 0xFFFF;//*/ -if (offset == 0x2C) +/*if (offset == 0x2C) data = 0x0000; if (offset == 0x2E) - data = 0x0008;//*/ // $0000 000F ($B) works, but not $0000 00001... or $7 + data = 0;//0x0008;//*/ + if (offset == UNKNOWN + 2) + data = CDROMBusRead(); #ifdef CDROM_LOG if ((offset & 0xFF) < 11 * 4) WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]); - WriteLog("CDROM: %s reading word $%04X from $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC)); + if (offset != UNKNOWN && offset != UNKNOWN + 2) + WriteLog("CDROM: %s reading word $%04X from $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC)); #endif return data; } @@ -154,10 +548,10 @@ if (offset == 0x2E) void CDROMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) { offset &= 0xFF; - cdrom_ram[offset] = data; + cdRam[offset] = data; #ifdef CDROM_LOG - if ((offset & 0xFF) < 11 * 4) + if ((offset & 0xFF) < 12 * 4) WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]); WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC)); #endif @@ -166,43 +560,759 @@ void CDROMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) void CDROMWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/) { offset &= 0xFF; - cdrom_ram[offset+0] = (data >> 8) & 0xFF; - cdrom_ram[offset+1] = data & 0xFF; - - // command register -/* - if (offset==0x0A) + SET16(cdRam, offset, data); + + // Command register +//Lesse what this does... Seems to work OK...! + if (offset == DS_DATA) { - cdrom_cmd=data; - if ((data&0xff00)==0x1500) + cdCmd = data; + if ((data & 0xFF00) == 0x0200) // Stop CD { - WriteLog("CDROM: setting mode 0x%.2x\n",data&0xff); - return; + cdPtr = 0; + WriteLog("CDROM: Stopping CD\n", data & 0xFF); } - if (data==0x7001) + else if ((data & 0xFF00) == 0x0300) // Read session TOC (short? overview?) { - uint32 offset=cdrom_ram[0x00]; - offset<<=8; - offset|=cdrom_ram[0x01]; - offset<<=8; - offset|=cdrom_ram[0x02]; - offset<<=8; - offset|=cdrom_ram[0x03]; - - uint32 size=cdrom_ram[0x04]; - offset<<=8; - offset|=cdrom_ram[0x05]; - - WriteLog("CDROM: READ(0x%.8x, 0x%.4x) [68k pc=0x%.8x]\n", offset, size, m68k_get_reg(NULL, M68K_REG_PC)); - return; + cdPtr = 0; + WriteLog("CDROM: Reading TOC for session #%u\n", data & 0xFF); + } +//Not sure how these three acknowledge... + else if ((data & 0xFF00) == 0x1000) // Seek to minute position + { + min = data & 0x00FF; + } + else if ((data & 0xFF00) == 0x1100) // Seek to second position + { + sec = data & 0x00FF; + } + else if ((data & 0xFF00) == 0x1200) // Seek to frame position + { + frm = data & 0x00FF; + block = (((min * 60) + sec) * 75) + frm; + cdBufPtr = 2352; // Ensure that SSI read will do so immediately + WriteLog("CDROM: Seeking to %u:%02u:%02u [block #%u]\n", min, sec, frm, block); + } + else if ((data & 0xFF00) == 0x1400) // Read "full" TOC for session + { + cdPtr = 0x60, + minTrack = CDIntfGetSessionInfo(data & 0xFF, 0), + maxTrack = CDIntfGetSessionInfo(data & 0xFF, 1); + trackNum = minTrack; + WriteLog("CDROM: Reading \"full\" TOC for session #%u (min=%u, max=%u)\n", data & 0xFF, minTrack, maxTrack); + } + else if ((data & 0xFF00) == 0x1500) // Set CDROM mode + { + // Mode setting is as follows: bit 0 set -> single speed, bit 1 set -> double, + // bit 3 set -> multisession CD, bit 3 unset -> audio CD + WriteLog("CDROM: Setting mode $%02X\n", data & 0xFF); + } + else if ((data & 0xFF00) == 0x1800) // Spin up session # + { + WriteLog("CDROM: Spinning up session #%u\n", data & 0xFF); + } + else if ((data & 0xFF00) == 0x5400) // Read # of sessions + { + WriteLog("CDROM: Reading # of sessions\n", data & 0xFF); + } + else if ((data & 0xFF00) == 0x7000) // Set oversampling rate + { + // 1 = none, 2 = 2x, 3 = 4x, 4 = 8x + uint32 rates[5] = { 0, 1, 2, 4, 8 }; + WriteLog("CDROM: Setting oversample rate to %uX\n", rates[(data & 0xFF)]); } else - WriteLog("CDROM: unknown command 0x%.4x\n",data); - } -//*/ + WriteLog("CDROM: Unknown command $%04X\n", data); + }//*/ + + if (offset == UNKNOWN + 2) + CDROMBusWrite(data); + #ifdef CDROM_LOG if ((offset & 0xFF) < 11 * 4) WriteLog("[%s] ", BReg[(offset & 0xFF) / 4]); - WriteLog("CDROM: %s writing word $%04X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC)); + if (offset != UNKNOWN && offset != UNKNOWN + 2) + WriteLog("CDROM: %s writing word $%04X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC)); +#endif +} + +// +// State machine for sending/receiving data along a serial bus +// + +enum ButchState { ST_INIT, ST_RISING, ST_FALLING }; +static ButchState currentState = ST_INIT; +static uint16 counter = 0; +static bool cmdTx = false; +static uint16 busCmd; +static uint16 rxData, txData; +static uint16 rxDataBit; +static bool firstTime = false; + +static void CDROMBusWrite(uint16 data) +{ +//This is kinda lame. What we should do is check for a 0->1 transition on either bits 0 or 1... +//!!! FIX !!! + +#ifdef CDROM_LOG + if (data & 0xFFF0) + WriteLog("CDROM: BusWrite write on unknown line: $%04X\n", data); +#endif + + switch (currentState) + { + case ST_INIT: + currentState = ST_RISING; + break; + case ST_RISING: + if (data & 0x0001) // Command coming + { + cmdTx = true; + counter = 0; + busCmd = 0; + } + else + { + if (cmdTx) + { + busCmd <<= 1; // Make room for next bit + busCmd |= (data & 0x04); // & put it in + counter++; + + if (counter == 9) + { + busCmd >>= 2; // Because we ORed bit 2, we need to shift right by 2 + cmdTx = false; + +//What it looks like: +//It seems that the $18x series reads from NVRAM while the +//$130, $14x, $100 series writes values to NVRAM... + if (busCmd == 0x180) + rxData = 0x0024;//1234; + else if (busCmd == 0x181) + rxData = 0x0004;//5678; + else if (busCmd == 0x182) + rxData = 0x0071;//9ABC; + else if (busCmd == 0x183) + rxData = 0xFF67;//DEF0; + else if (busCmd == 0x184) + rxData = 0xFFFF;//892F; + else if (busCmd == 0x185) + rxData = 0xFFFF;//8000; + else + rxData = 0x0001; +// rxData = 0x8349;//8000;//0F67; + + counter = 0; + firstTime = true; + txData = 0; +#ifdef CDROM_LOG + WriteLog("CDROM: *** BusWrite got command $%04X\n", busCmd); +#endif + } + } + else + { + txData = (txData << 1) | ((data & 0x04) >> 2); +//WriteLog("[%s]", data & 0x04 ? "1" : "0"); + + rxDataBit = (rxData & 0x8000) >> 12; + rxData <<= 1; + counter++; +#ifdef CDROM_LOG + if (counter == 16) + WriteLog("CDROM: *** BusWrite got extra command $%04X\n", txData); +#endif + } + } + + currentState = ST_FALLING; + break; + case ST_FALLING: + currentState = ST_INIT; + break; + } +} + +static uint16 CDROMBusRead(void) +{ +// It seems the counter == 0 simply waits for a single bit acknowledge-- !!! FIX !!! +// Or does it? Hmm. It still "pumps" 16 bits through above, so how is this special? +// Seems to be because it sits and looks at it as if it will change. Dunno! +#ifdef CDROM_LOG + if ((counter & 0x0F) == 0) + { + if (counter == 0 && rxDataBit == 0) + { + if (firstTime) + { + firstTime = false; + WriteLog("0...\n"); + } + } + else + WriteLog("%s\n", rxDataBit ? "1" : "0"); + } + else + WriteLog("%s", rxDataBit ? "1" : "0"); #endif + + return rxDataBit; +} + +// +// This simulates a read from BUTCH over the SSI to JERRY. Uses real reading! +// +//temp, until I can fix my CD image... Argh! +static uint8 cdBuf2[2532 + 96], cdBuf3[2532 + 96]; +uint16 GetWordFromButchSSI(uint32 offset, uint32 who/*= UNKNOWN*/) +{ + bool go = ((offset & 0x0F) == 0x0A || (offset & 0x0F) == 0x0E ? true : false); + + if (!go) + return 0x000; + +// The problem comes in here. Really, we should generate the IRQ once we've stuffed +// our values into the DAC L/RRXD ports... +// But then again, the whole IRQ system needs an overhaul in order to make it more +// cycle accurate WRT to the various CPUs. Right now, it's catch-as-catch-can, which +// means that IRQs get serviced on scanline boundaries instead of when they occur. + cdBufPtr += 2; + + if (cdBufPtr >= 2352) + { +WriteLog("CDROM: %s reading block #%u...\n", whoName[who], block); + //No error checking. !!! FIX !!! +//NOTE: We have to subtract out the 1st track start as well (in cdintf_foo.cpp)! +// CDIntfReadBlock(block - 150, cdBuf); + +//Crappy kludge for shitty shit. Lesse if it works! + CDIntfReadBlock(block - 150, cdBuf2); + CDIntfReadBlock(block - 149, cdBuf3); + for(int i=0; i<2352-4; i+=4) + { + cdBuf[i+0] = cdBuf2[i+4]; + cdBuf[i+1] = cdBuf2[i+5]; + cdBuf[i+2] = cdBuf2[i+2]; + cdBuf[i+3] = cdBuf2[i+3]; + } + cdBuf[2348] = cdBuf3[0]; + cdBuf[2349] = cdBuf3[1]; + cdBuf[2350] = cdBuf2[2350]; + cdBuf[2351] = cdBuf2[2351];//*/ + + block++, cdBufPtr = 0; + } + +/*extern bool doDSPDis; +if (block == 244968) + doDSPDis = true;//*/ + +WriteLog("[%04X:%01X]", GET16(cdBuf, cdBufPtr), offset & 0x0F); +if (cdBufPtr % 32 == 30) + WriteLog("\n"); + +// return GET16(cdBuf, cdBufPtr); +//This probably isn't endian safe... +// But then again... It seems that even though the data on the CD is organized as +// LL LH RL RH the way it expects to see the data is RH RL LH LL. +// D'oh! It doesn't matter *how* the data comes in, since it puts each sample into +// its own left or right side queue, i.e. it reads them 32 bits at a time and puts +// them into their L/R channel queues. It does seem, though, that it expects the +// right channel to be the upper 16 bits and the left to be the lower 16. + return (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0]; } + +bool ButchIsReadyToSend(void) +{ + return (cdRam[I2CNTRL + 3] & 0x02 ? true : false); +} + +// +// This simulates a read from BUTCH over the SSI to JERRY. Uses real reading! +// +void SetSSIWordsXmittedFromButch(void) +{ + +// The problem comes in here. Really, we should generate the IRQ once we've stuffed +// our values into the DAC L/RRXD ports... +// But then again, the whole IRQ system needs an overhaul in order to make it more +// cycle accurate WRT to the various CPUs. Right now, it's catch-as-catch-can, which +// means that IRQs get serviced on scanline boundaries instead of when they occur. + +// NOTE: The CD BIOS uses the following SMODE: +// DAC: M68K writing to SMODE. Bits: WSEN FALLING [68K PC=00050D8C] + cdBufPtr += 4; + + if (cdBufPtr >= 2352) + { +WriteLog("CDROM: Reading block #%u...\n", block); + //No error checking. !!! FIX !!! +//NOTE: We have to subtract out the 1st track start as well (in cdintf_foo.cpp)! +// CDIntfReadBlock(block - 150, cdBuf); + +//Crappy kludge for shitty shit. Lesse if it works! +//It does! That means my CD is WRONG! FUCK! + +// But, then again, according to Belboz at AA the two zeroes in front *ARE* necessary... +// So that means my CD is OK, just this method is wrong! +// It all depends on whether or not the interrupt occurs on the RISING or FALLING edge +// of the word strobe... !!! FIX !!! + +// When WS rises, left channel was done transmitting. When WS falls, right channel is done. +// CDIntfReadBlock(block - 150, cdBuf2); +// CDIntfReadBlock(block - 149, cdBuf3); + CDIntfReadBlock(block, cdBuf2); + CDIntfReadBlock(block + 1, cdBuf3); + memcpy(cdBuf, cdBuf2 + 2, 2350); + cdBuf[2350] = cdBuf3[0]; + cdBuf[2351] = cdBuf3[1];//*/ + + block++, cdBufPtr = 0; + +/*extern bool doDSPDis; +static int foo = 0; +if (block == 244968) +{ + foo++; +WriteLog("\n***** foo = %u, block = %u *****\n\n", foo, block); + if (foo == 2) + doDSPDis = true; +}//*/ + } + + +WriteLog("[%02X%02X %02X%02X]", cdBuf[cdBufPtr+1], cdBuf[cdBufPtr+0], cdBuf[cdBufPtr+3], cdBuf[cdBufPtr+2]); +if (cdBufPtr % 32 == 28) + WriteLog("\n"); + +//This probably isn't endian safe... +// But then again... It seems that even though the data on the CD is organized as +// LL LH RL RH the way it expects to see the data is RH RL LH LL. +// D'oh! It doesn't matter *how* the data comes in, since it puts each sample into +// its own left or right side queue, i.e. it reads them 32 bits at a time and puts +// them into their L/R channel queues. It does seem, though, that it expects the +// right channel to be the upper 16 bits and the left to be the lower 16. + +// This behavior is strictly a function of *where* the WS creates an IRQ. If the data +// is shifted by two zeroes (00 00 in front of the data file) then this *is* the +// correct behavior, since the left channel will be xmitted followed by the right + +// Now we have definitive proof: The MYST CD shows a word offset. So that means we have +// to figure out how to make that work here *without* having to load 2 sectors, offset, etc. +// !!! FIX !!! + lrxd = (cdBuf[cdBufPtr + 3] << 8) | cdBuf[cdBufPtr + 2], + rrxd = (cdBuf[cdBufPtr + 1] << 8) | cdBuf[cdBufPtr + 0]; +} + +/* +[18667] +TOC for MYST + +CDINTF: Disc summary + # of sessions: 2, # of tracks: 10 + Session info: + 1: min track= 1, max track= 1, lead out= 1:36:67 + 2: min track= 2, max track=10, lead out=55:24:71 + Track info: + 1: start= 0:02:00 + 2: start= 4:08:67 + 3: start= 4:16:65 + 4: start= 4:29:19 + 5: start=29:31:03 + 6: start=33:38:50 + 7: start=41:38:60 + 8: start=44:52:18 + 9: start=51:51:22 + 10: start=55:18:73 + +CDROM: Read sector 18517 (18667 - 150)... + +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 + +Raw P-W subchannel data: + +00: 80 80 C0 80 80 80 80 C0 80 80 80 80 80 80 C0 80 +10: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 +20: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 C0 +30: 80 80 80 80 80 80 80 80 80 80 80 80 80 C0 80 80 +40: 80 80 80 80 C0 80 80 80 80 C0 C0 80 80 C0 C0 80 +50: C0 80 80 C0 C0 C0 80 80 C0 80 80 80 C0 80 80 80 + +P subchannel data: FF FF FF FF FF FF FF FF FF FF FF FF +Q subchannel data: 21 02 00 00 00 01 00 04 08 66 9C 88 + +Run address: $5000, Length: $18380 +*/ + + +/* +CD_read function from the CD BIOS: Note that it seems to direct the EXT1 interrupt +to the GPU--so that would mean *any* interrupt that BUTCH generates would be routed +to the GPU... + +read: + btst.l #31,d0 + bne.w .play + subq.l #4,a0 ; Make up for ISR pre-increment + move.l d0,-(sp) + move.l BUTCH,d0 + and.l #$ffff0000,d0 + move.l d0,BUTCH ; NO INTERRUPTS!!!!!!!!!!! + move.l (sp)+,d0 +; move.l #0,BUTCH + + move.w #$101,J_INT + + move.l d1,-(sp) + move.l I2CNTRL,d1 ;Read I2S Control Register + bclr #2,d1 ; Stop data + move.l d1,I2CNTRL + move.l (sp)+,d1 + + move.l PTRLOC,a2 + move.l a0,(a2)+ + move.l a1,(a2)+ + move.l #0,(a2)+ + + btst.b #7,INITTYPE + beq .not_bad + move.l PTRLOC,a0 + asl.l #5,d2 + + move.l d2,-(sp) + + or.l #$089a3c1a,d2 ; These instructions include the bclr + move.l d2,188(a0) + + move.l (sp)+,d2 + + swap d2 + or.l #$3c1a1838,d2 ; These instructions include the bclr + move.l d2,196(a0) + + move.l #16,(a2)+ + move.l d1,(a2) + +.not_bad: + + move.w DS_DATA,d1 ; Clear any pending DSARX states + move.l I2CNTRL,d1 ; Clear any pending errors + +; Drain the FIFO so that we don't get overloaded + +.dump: + move.l FIFO_DATA,d1 + move.l I2CNTRL,d1 + btst #4,d1 + bne.b .dump + +.butch_go: + move.l BUTCH,d1 + and.l #$FFFF0000,d1 + or.l #%000100001,d1 ;Enable DSARX interrupt + move.l d1,BUTCH +; move.l #%000100001,BUTCH ;Enable DSARX interrupt + +; Do a play @ + +.play: move.l d0,d1 ; mess with copy in d1 + lsr.l #8,d1 ; shift the byte over + lsr.w #8,d1 + or.w #$1000,d1 ; format it for goto + move.w d1,DS_DATA ; DSA tx + bsr.b DSA_tx + + move.l d0,d1 ; mess with copy in d1 + lsr.w #8,d1 + or.w #$1100,d1 ; format it for goto + move.w d1,DS_DATA ; DSA tx + bsr.b DSA_tx + + move.l d0,d1 ; mess with copy in d1 + and.w #$00FF,d1 ; mask for minutes + or.w #$1200,d1 ; format it for goto + move.w d1,DS_DATA ; DSA tx + bsr.b DSA_tx + + rts + + +**************************** +* Here's the GPU interrupt * +**************************** + +JERRY_ISR: + movei #G_FLAGS,r30 + load (r30),r29 ;read the flags + + movei #BUTCH,r24 + +make_ptr: + move pc,Ptrloc + movei #(make_ptr-PTRPOS),TEMP + sub TEMP,Ptrloc + +HERE: + move pc,r25 + movei #(EXIT_ISR-HERE),r27 + add r27,r25 + +; Is this a DSARX interrupt? + + load (r24),r27 ;check for DSARX int pending + btst #13,r27 + jr z,fifo_read ; This should ALWAYS fall thru the first time + +; Set the match bit, to allow data +; moveq #3,r26 ; enable FIFO only +; Don't just jam a value +; Clear the DSARX and set FIFO + bclr #5,r27 + bset #1,r27 + store r27,(r24) + addq #$10,r24 + load (r24),r27 + bset #2,r27 + store r27,(r24) ; Disable SUBCODE match + +; Now we clear the DSARX interrupt in Butch + + subq #12,r24 ; does what the above says + load (r24),r26 ;Clears DSA pending interrupt + addq #6,r24 + loadw (r24),r27 ; Read DSA response + btst #10,r27 ; Check for error + jr nz,error + or r26,r26 + jump (r25) +; nop + +fifo_read: +; Check for ERROR!!!!!!!!!!!!!!!!!!!!! + btst #14,r27 + jr z,noerror + bset #31,r27 +error: + addq #$10,r24 + load (r24),TEMP + or TEMP,TEMP + subq #$10,r24 + load (Ptrloc),TEMP + addq #8,Ptrloc + store TEMP,(Ptrloc) + subq #8,Ptrloc +noerror: + load (Ptrloc),Dataptr ;get pointer + +; Check to see if we should stop + addq #4,Ptrloc + load (Ptrloc),TEMP + subq #4,Ptrloc + cmp Dataptr,TEMP + jr pl,notend +; nop + bclr #0,r27 + store r27,(r24) + +notend: + movei #FIFO_DATA,CDdata + move CDdata,r25 + addq #4,CDdata +loptop: + load (CDdata),TEMP + load (r25),r30 + load (CDdata),r21 + load (r25),r22 + load (CDdata),r24 + load (r25),r20 + load (CDdata),r19 + load (r25),r18 + addq #4,Dataptr + store TEMP,(Dataptr) + addqt #4,Dataptr + store r30,(Dataptr) + addqt #4,Dataptr + store r21,(Dataptr) + addqt #4,Dataptr + store r22,(Dataptr) + addqt #4,Dataptr + store r24,(Dataptr) + addqt #4,Dataptr + store r20,(Dataptr) + addqt #4,Dataptr + store r19,(Dataptr) + addqt #4,Dataptr + store r18,(Dataptr) + + store Dataptr,(Ptrloc) + +exit_isr: + movei #J_INT,r24 ; Acknowledge in Jerry + moveq #1,TEMP + bset #8,TEMP + storew TEMP,(r24) + +.if FLAG +; Stack r18 + load (r31),r18 + addq #4,r31 + +; Stack r19 + load (r31),r19 + addq #4,r31 + +; Stack r20 + load (r31),r20 + addq #4,r31 + +; Stack r21 + load (r31),r21 + addq #4,r31 + +; Stack r22 + load (r31),r22 + addq #4,r31 + +; Stack r23 + load (r31),r23 + addq #4,r31 + +; Stack r26 + load (r31),r26 + addq #4,r31 + +; Stack r27 + load (r31),r27 + addq #4,r31 + +; Stack r24 + load (r31),r24 + addq #4,r31 + +; Stack r25 + load (r31),r25 + addq #4,r31 +.endif + + movei #G_FLAGS,r30 + +;r29 already has flags + bclr #3,r29 ;IMASK + bset #10,r29 ;Clear DSP int bit in TOM + + load (r31),r28 ;Load return address + + + addq #2,r28 ;Fix it up + addq #4,r31 + jump (r28) ;Return + store r29,(r30) ;Restore broken flags + + + align long + +stackbot: + ds.l 20 +STACK: + + +*/ + -- 2.37.2