mirror of
https://github.com/CTR-tools/CTR-ModSDK.git
synced 2025-02-23 23:00:57 +00:00
1189 lines
23 KiB
C
1189 lines
23 KiB
C
|
|
// called "CDSYS" because of debug strings
|
|
// "CDSYS_SetXAToLang", "CDSYS_XASeek", "CDSYS_XAPlay"
|
|
|
|
// CDSYS_Init
|
|
undefined4 FUN_8001c360(int param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// unused in all found builds of the game,
|
|
// boolDebugMachine = false?
|
|
DAT_8008e528 = 0;
|
|
|
|
// bool boolUseDisc
|
|
DAT_8008d6b0 = param_1;
|
|
|
|
// If you are using disc
|
|
if (param_1 != 0)
|
|
{
|
|
// initialize the CD
|
|
iVar1 = CdInit();
|
|
|
|
// if you fail to initialize CD
|
|
if (iVar1 == 0)
|
|
{
|
|
// fall back to parallel port (Naughty Dog Devs only)
|
|
DAT_8008d6b0 = 0;
|
|
return 0;
|
|
}
|
|
CdSetDebug(1);
|
|
}
|
|
|
|
// stream mode is null
|
|
DAT_8008d6ac = 0xffffffff;
|
|
|
|
// bool_XnfLoaded
|
|
DAT_8008d6b4 = 0;
|
|
|
|
// XA_State
|
|
DAT_8008d708 = 0;
|
|
|
|
// XA is not finished (nor started)
|
|
DAT_8008d6b8 = 0;
|
|
|
|
// countFail_CdSyncCallback
|
|
DAT_8008d720 = 0;
|
|
|
|
// countPass_CdReadyCallback
|
|
DAT_8008d704 = 0;
|
|
|
|
// countFail_CdReadyCallback
|
|
DAT_8008d724 = 0;
|
|
|
|
// XA_CurrOffset
|
|
DAT_8008d6f8 = 0;
|
|
|
|
// countPass_CdTransferCallback
|
|
DAT_8008d6d8 = 0;
|
|
|
|
// XA_Playing_Category
|
|
DAT_8008d6e4 = 0;
|
|
|
|
// XA_Playing_Index
|
|
DAT_8008d6e0 = 0;
|
|
|
|
// XA_StartPos
|
|
DAT_8008d6f0 = 0;
|
|
|
|
// XA_EndPos
|
|
DAT_8008d710 = 0;
|
|
|
|
// XA_VolumeBitshift
|
|
DAT_8008d70c = 0;
|
|
|
|
// XA_VolumeDeduct
|
|
DAT_8008d6c8 = 0;
|
|
|
|
// XA_MaxSampleVal
|
|
DAT_8008d714 = 0;
|
|
|
|
// XA_MaxSampleValInArr
|
|
DAT_8008d6f4 = 0;
|
|
|
|
// irqAddr
|
|
DAT_8008d6c4 = 0;
|
|
|
|
// unused
|
|
DAT_8008d700 = 0;
|
|
|
|
// XA_CurrPos
|
|
DAT_8008d6d4 = 0;
|
|
|
|
// XA_PausePos
|
|
DAT_8008d6ec = 0;
|
|
|
|
// CDSYS_SetMode_StreamData
|
|
FUN_8001c470();
|
|
|
|
// Just like loading LNG (for text),
|
|
// Load XA (for audio) with 1 for ENG
|
|
CDSYS_SetXAToLang(1);
|
|
|
|
// Voiceline_PoolClear
|
|
FUN_8002cae0();
|
|
return 1;
|
|
}
|
|
|
|
|
|
// CDSYS_GetFilePosInt
|
|
// param1 is the file it is searching for,
|
|
// param2 is the position that will return
|
|
// function returns true or false if it worked or failed
|
|
uint FUN_8001c420(char *param_1,int *param_2)
|
|
|
|
{
|
|
CdlFILE *pCVar1;
|
|
int iVar2;
|
|
CdlFILE CStack32;
|
|
|
|
// cpVar1 and CStack32 are the same
|
|
// param_1 is the string of the file searched,
|
|
// pCVar1 is the CdlFILE that corresponds
|
|
pCVar1 = CdSearchFile(&CStack32,param_1);
|
|
|
|
// if file was found
|
|
if (pCVar1 != (CdlFILE *)0x0)
|
|
{
|
|
// Convert file's CD position to int
|
|
iVar2 = CdPosToInt((CdlLOC *)&CStack32);
|
|
|
|
// set param2 to cd position
|
|
*param_2 = iVar2;
|
|
}
|
|
|
|
// return true if it found file, or false if it failed
|
|
return (uint)(pCVar1 != (CdlFILE *)0x0);
|
|
}
|
|
|
|
|
|
// CDSYS_SetMode_StreamData
|
|
void FUN_8001c470(void)
|
|
|
|
{
|
|
u_char local_10 [8];
|
|
|
|
if (
|
|
// boolUseDisc
|
|
// if you are using CD instead of parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// if stream mode is not data
|
|
(DAT_8008d6ac != 0)
|
|
)
|
|
{
|
|
// bool_XnfLoaded
|
|
if (DAT_8008d6b4 != 0)
|
|
{
|
|
// CDSYS_XAPauseForce
|
|
FUN_8001cfec();
|
|
}
|
|
|
|
// https://www.cybdyn-systems.com.au/forum/viewtopic.php?t=1956
|
|
// CdControl('\x0e',local_10,(u_char *)0x0);
|
|
// param_1: 0xe = CdlSetmode
|
|
// param_2: 0x80 = Speed mode (separate modes exist)
|
|
// param_3: 0 = normal speed, 1 = double speed
|
|
|
|
// Set Mode to Data
|
|
local_10[0] = CdlModeSpeed;
|
|
CdControl(CdlSetmode, local_10, 0);
|
|
|
|
// XA_State
|
|
DAT_8008d708 = 0;
|
|
|
|
// stream mode is now data
|
|
DAT_8008d6ac = 0;
|
|
|
|
// bool_XnfLoaded
|
|
if (DAT_8008d6b4 != 0)
|
|
{
|
|
// called when CdControl is complete
|
|
CdSyncCallback(0);
|
|
|
|
// called when data is streamed
|
|
CdReadyCallback((CdlCB)0x0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SetMode_StreamAudio
|
|
void FUN_8001c4f4(void)
|
|
|
|
{
|
|
u_char local_10 [8];
|
|
|
|
if (
|
|
(
|
|
// If you are using CD instead of parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// bool_XnfLoaded
|
|
(DAT_8008d6b4 != 0)
|
|
) &&
|
|
|
|
// if stream mode is not audio
|
|
(DAT_8008d6ac != 1)
|
|
)
|
|
{
|
|
// https://www.cybdyn-systems.com.au/forum/viewtopic.php?t=1956
|
|
// CdControl('\x0e',local_10,(u_char *)0x0);
|
|
// param_1: 0xe = CdlSetmode
|
|
// param_2: 0xE8 = set speed, play ADPCM, set sector
|
|
|
|
// Set Mode to Audio
|
|
local_10[0] = -0x18; // 0xE8
|
|
CdControl('\x0e',local_10,(u_char *)0x0);
|
|
|
|
// set stream mode to audio
|
|
DAT_8008d6ac = 1;
|
|
|
|
// XA_State
|
|
DAT_8008d708 = 0;
|
|
|
|
// called when CdControl is complete
|
|
CdSyncCallback(FUN_8001c7a4);
|
|
|
|
// called when audio is streamed
|
|
CdReadyCallback(FUN_8001c7fc);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// CDSYS_SetXAToLang
|
|
// 8001c56c
|
|
// Name found in Aug 5 Prototype
|
|
// loads correct XNF file and checks if all XA files are present on the disk
|
|
// param_1 - language index
|
|
undefined4 CDSYS_SetXAToLang(int param_1)
|
|
|
|
{
|
|
char cVar1;
|
|
undefined4 uVar2;
|
|
int *piVar3;
|
|
int iVar4;
|
|
char **ppcVar5;
|
|
int iVar6;
|
|
byte *pbVar7;
|
|
int iVar8;
|
|
int iVar9;
|
|
undefined auStack32 [8];
|
|
|
|
// If you are using parallel port instead of CD
|
|
if (DAT_8008d6b0 == 0) {
|
|
uVar2 = 1;
|
|
}
|
|
|
|
// If you are using CD instead of parallel port
|
|
else {
|
|
|
|
//check lang id overflow. what's interesting is that the id is not checked during lang file loading
|
|
if (param_1 < 8)
|
|
{
|
|
// bool_XnfLoaded
|
|
DAT_8008d6b4 = 0;
|
|
|
|
// CDSYS_SetMode_StreamData
|
|
FUN_8001c470();
|
|
|
|
//get current lang string (ENG, JPN, etc)
|
|
ppcVar5 = &PTR_DAT_80081050 + param_1;
|
|
|
|
//update xa file paths
|
|
strncpy(s_ENG_XNF_1_80081000,*ppcVar5,3);
|
|
strncpy(s_ENG_EXTRA_S00_XA_1_80081024,*ppcVar5,3);
|
|
strncpy(s_ENG_GAME_S00_XA_1_8008103c,*ppcVar5,3);
|
|
|
|
// read XNF file into buffer
|
|
piVar3 = (int *)FUN_80032344(&DAT_80080ffc,0,auStack32);
|
|
|
|
// if reading XNF failed
|
|
if (piVar3 == (int *)0x0)
|
|
{
|
|
// quit the function
|
|
return 0;
|
|
}
|
|
|
|
// only load file if first 4 bytes are "XINF"
|
|
// and if the next 4 bytes (version) is 102 (0x66).
|
|
// Aug 5 had 100, Sep 3 had 101, 94426+ had 102
|
|
if ((*piVar3 == DAT_8008cfc0) && (piVar3[1] == 0x66))
|
|
{
|
|
// Get number of types
|
|
DAT_8008d6dc = piVar3[2];
|
|
|
|
// only continue if that's 3
|
|
if (DAT_8008d6dc == 3) {
|
|
|
|
// each of these is a pointer to
|
|
// an array of three ints,
|
|
// Music, Extra, Game
|
|
|
|
// ptrArray_NumXAs
|
|
DAT_8008d6fc = piVar3 + 5;
|
|
|
|
// ptrArray_firstXaIndex
|
|
DAT_8008d71c = piVar3 + 8;
|
|
|
|
// ptrArray_numSongs
|
|
DAT_8008d6cc = piVar3 + 0xb;
|
|
|
|
// ptrArray_firstSongIndex
|
|
DAT_8008d6d0 = piVar3 + 0xe;
|
|
|
|
// not an array of 3 ints,
|
|
// array of a huge ton of data
|
|
// ptrArray_XaCdPos
|
|
DAT_8008d718 = piVar3 + 0x11;
|
|
|
|
iVar9 = 0;
|
|
iVar8 = 0;
|
|
|
|
// pointer to array[3] of { byte, byte, short, ptr }
|
|
// where ptr is pointer to file path \XA\MUSIC\S00.XA;1.
|
|
// byte - digit char indices to swap (00)
|
|
// short - null
|
|
|
|
// &sdata->audioMeta[0]
|
|
pbVar7 = &DAT_80081070;
|
|
|
|
// pointer to actual XA entries (big array of uint (byte[4])),
|
|
// comes after an array for every XA file
|
|
|
|
// &ptrXNF->data[ptrXNF->numXAs_total]
|
|
DAT_8008d6e8 = DAT_8008d718 + piVar3[3];
|
|
|
|
// This loop bakes an array of CD Postions
|
|
// for every XA file, so we dont need to
|
|
// search the disc when we need them
|
|
|
|
//for each xa group
|
|
do {
|
|
iVar6 = 0;
|
|
|
|
//if there are xa files in the current group
|
|
if (0 < *(int *)(iVar8 + (int)DAT_8008d6fc)) {
|
|
|
|
//for each file entry
|
|
do {
|
|
cVar1 = (char)(iVar6 / 10);
|
|
//swap 00 in S00.XA with correct digits
|
|
*(char *)(*(int *)(pbVar7 + 4) + (uint)*pbVar7) = cVar1 + '0';
|
|
*(char *)(*(int *)(pbVar7 + 4) + (uint)pbVar7[1]) = (char)iVar6 + cVar1 * -10 + '0';
|
|
|
|
// CDSYS_GetFilePosInt
|
|
// get cd position of param1, store position into param2
|
|
iVar4 = FUN_8001c420(*(undefined4 *)(pbVar7 + 4),
|
|
DAT_8008d718 + *(int *)(iVar8 + (int)DAT_8008d71c) + iVar6);
|
|
iVar6 = iVar6 + 1;
|
|
|
|
// if file was not found, quit the function,
|
|
// return false for the function
|
|
if (iVar4 == 0) goto LAB_8001c654;
|
|
|
|
} while (iVar6 < *(int *)(iVar8 + (int)DAT_8008d6fc));
|
|
}
|
|
|
|
//increment relative pointer to xa group
|
|
iVar8 = iVar8 + 4;
|
|
|
|
// increment counter
|
|
iVar9 = iVar9 + 1;
|
|
|
|
// next type (8 bytes each)
|
|
pbVar7 = pbVar7 + 8;
|
|
|
|
// if all "types" are loaded
|
|
if (DAT_8008d6dc <= iVar9)
|
|
{
|
|
// bool_XnfLoaded
|
|
DAT_8008d6b4 = 1;
|
|
return 1;
|
|
}
|
|
} while( true );
|
|
}
|
|
}
|
|
}
|
|
LAB_8001c654:
|
|
uVar2 = 0;
|
|
}
|
|
return uVar2;
|
|
}
|
|
|
|
// CDSYS_XaCallbackCdSync
|
|
void FUN_8001c7a4(char param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// if result == CdlComplete
|
|
if (param_1 == '\x02')
|
|
{
|
|
// string of command
|
|
iVar1 = CdLastCom();
|
|
|
|
if (iVar1 - 0x15U < 2) {
|
|
DAT_8008d708 = 0;
|
|
}
|
|
}
|
|
|
|
// if fail
|
|
else
|
|
{
|
|
// count fails
|
|
DAT_8008d720 = DAT_8008d720 + 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// CDSYS_XaCallbackCdReady
|
|
void FUN_8001c7fc(char param_1)
|
|
|
|
{
|
|
// if result == CdlDataReady
|
|
if (param_1 == '\x01')
|
|
{
|
|
// cdlFile_CdReady (half of a CdlFILE struct)
|
|
CdGetSector(&DAT_8008e6b8,3);
|
|
DAT_8008d6d4 = CdPosToInt((CdlLOC *)&DAT_8008e6b8);
|
|
|
|
if (
|
|
// if XA is queued to start (CD seeking?)
|
|
(DAT_8008d708 == 2) &&
|
|
|
|
// if XA_CurrPos is more than XA_StartPos
|
|
(DAT_8008d6f0 <= DAT_8008d6d4)
|
|
)
|
|
{
|
|
// XA is now playing
|
|
DAT_8008d708 = 3;
|
|
|
|
// XA_CurrOffset = CurrPos - StartPos
|
|
DAT_8008d6f8 = (DAT_8008d6d4 - DAT_8008d6f0) * 4;
|
|
}
|
|
|
|
if (
|
|
// if XA is playing
|
|
(DAT_8008d708 == 3) &&
|
|
|
|
// if XA_CurrPos is more than XA_EndPos
|
|
(DAT_8008d710 < DAT_8008d6d4)
|
|
)
|
|
{
|
|
|
|
// XA should stop
|
|
DAT_8008d708 = 4;
|
|
|
|
// disable music
|
|
DAT_8008d6c8 = 0x400;
|
|
}
|
|
|
|
// count success
|
|
DAT_8008d704 = DAT_8008d704 + 1;
|
|
}
|
|
|
|
// if fail
|
|
else
|
|
{
|
|
// count fails
|
|
DAT_8008d724 = DAT_8008d724 + 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SpuCallbackIRQ
|
|
void FUN_8001c8e4(void)
|
|
|
|
{
|
|
// disable IRQ, now that it's finished
|
|
SpuSetIRQ(0);
|
|
|
|
/*
|
|
|
|
From LibRef
|
|
When you call SpuReadDecodedData(), the SPU copies data from its buffers to the SpuDecodeData struct
|
|
in main memory that you specify. It copies the data one-half buffer (0x200 bytes) at a time, and returns a
|
|
code specifying which half of the buffer is currently being written to, so you can use the data from the other
|
|
half.
|
|
*/
|
|
|
|
// 5 = SPU_CDONLY
|
|
SpuReadDecodedData((SpuDecodedData *)&DAT_8008dd28,5);
|
|
|
|
if (
|
|
// if XA is not finished
|
|
(DAT_8008d6b8 == 0) &&
|
|
|
|
// if XA is requested to stop,
|
|
// either by CdReadyCallback,
|
|
// or CDSYS_XAPauseRequest
|
|
(DAT_8008d708 == 4)
|
|
)
|
|
{
|
|
// 8008d6c8 is either 0 or 0x400
|
|
// 8008d70c is volume of music
|
|
|
|
DAT_8008d70c = DAT_8008d70c - DAT_8008d6c8;
|
|
|
|
// the goal is to gradually
|
|
// reduce audio slowly over time,
|
|
// otherwise intro-race song still
|
|
// plays when you pause game
|
|
|
|
// if volume is less than zero
|
|
if (DAT_8008d70c < 0)
|
|
{
|
|
// set audio to zero
|
|
DAT_8008d70c = 0;
|
|
|
|
// XA is finished
|
|
DAT_8008d6b8 = 1;
|
|
}
|
|
|
|
SpuSetCommonCDVolume((short)DAT_8008d70c,(short)DAT_8008d70c);
|
|
}
|
|
DAT_8008d6f8 = DAT_8008d6f8 + 1;
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SpuCallbackTransfer
|
|
void FUN_8001c984(void)
|
|
|
|
{
|
|
// irqAddr
|
|
if (DAT_8008d6c4 == 0)
|
|
{
|
|
// irqAddr
|
|
DAT_8008d6c4 = 0x200;
|
|
}
|
|
else
|
|
{
|
|
// irqAddr
|
|
DAT_8008d6c4 = 0;
|
|
}
|
|
|
|
// interrupt SPU when this address
|
|
// is written, or read, (XA?)
|
|
SpuSetIRQAddr(DAT_8008d6c4);
|
|
|
|
// set interrupt request
|
|
SpuSetIRQ(1);
|
|
|
|
// countPass_CdTransferCallback
|
|
DAT_8008d6d8 = DAT_8008d6d8 + 1;
|
|
|
|
// CDSYS_SpuGetMaxSample
|
|
FUN_8001ca98();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SpuEnableIRQ
|
|
void FUN_8001c9e4(void)
|
|
|
|
{
|
|
undefined2 *puVar1;
|
|
int iVar2;
|
|
|
|
// Erase SpuDecodedData,
|
|
// wipe it all to zeros
|
|
iVar2 = 0x1ff;
|
|
puVar1 = &DAT_8008e126;
|
|
DAT_8008d714 = 0;
|
|
DAT_8008d6f4 = 0;
|
|
do {
|
|
*puVar1 = 0;
|
|
iVar2 = iVar2 + -1;
|
|
puVar1 = puVar1 + -1;
|
|
} while (-1 < iVar2);
|
|
|
|
// transfer by DMA
|
|
SpuSetTransferMode(0);
|
|
|
|
SpuSetTransferCallback(FUN_8001c984);
|
|
SpuSetIRQCallback(FUN_8001c8e4);
|
|
|
|
// irqAddr
|
|
DAT_8008d6c4 = 0x200;
|
|
|
|
// unused
|
|
DAT_8008d700 = 0;
|
|
|
|
// interrupt SPU when this address
|
|
// is written, or read
|
|
SpuSetIRQAddr(0x200);
|
|
|
|
// set interrupt request (ON)
|
|
SpuSetIRQ(1);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SpuDisableIRQ
|
|
void FUN_8001ca64(void)
|
|
|
|
{
|
|
// set interrupt request (OFF)
|
|
SpuSetIRQ(0);
|
|
|
|
SpuSetIRQCallback((SpuIRQCallbackProc)0x0);
|
|
SpuSetTransferCallback((SpuTransferCallbackProc)0x0);
|
|
DAT_8008d6f4 = 0;
|
|
DAT_8008d714 = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_SpuGetMaxSample
|
|
void FUN_8001ca98(void)
|
|
|
|
{
|
|
bool bVar1;
|
|
uint uVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int *piVar5;
|
|
short *psVar6;
|
|
uint uVar7;
|
|
short sVar8;
|
|
|
|
_sVar8 = 0;
|
|
sVar8 = 0;
|
|
|
|
// if you are using CD instead of parallel port
|
|
if (DAT_8008d6b0 != 0) {
|
|
uVar2 = 0x100;
|
|
|
|
// if irqAddr == 0x0, range {0x0 - 0x100}
|
|
if (DAT_8008d6c4 == 0) {
|
|
uVar2 = 0;
|
|
uVar7 = 0x100;
|
|
}
|
|
|
|
// otherwise, range {0x100 - 0x200}
|
|
else
|
|
{
|
|
uVar7 = 0x200;
|
|
}
|
|
|
|
// curr < end
|
|
if (uVar2 < uVar7)
|
|
{
|
|
// decoded SPU data
|
|
psVar6 = &DAT_8008dd28 + uVar2;
|
|
|
|
// loop through region
|
|
do
|
|
{
|
|
iVar3 = (int)*psVar6;
|
|
|
|
// absolute value
|
|
if (iVar3 < 0) {
|
|
iVar3 = -iVar3;
|
|
}
|
|
|
|
// if larger than cur_max
|
|
if (_sVar8 << 0x10 < iVar3 << 0x10)
|
|
{
|
|
// set new cur_max
|
|
_sVar8 = iVar3;
|
|
}
|
|
|
|
// copy max
|
|
sVar8 = (short)_sVar8;
|
|
|
|
uVar2 = uVar2 + 1;
|
|
psVar6 = psVar6 + 1;
|
|
} while ((int)uVar2 < (int)uVar7);
|
|
}
|
|
|
|
// save max
|
|
DAT_8008d714 = (int)sVar8;
|
|
|
|
// XA_MaxSampleValArr
|
|
piVar5 = &DAT_8008e6c8 + DAT_8008d6bc;
|
|
|
|
DAT_8008d6bc = DAT_8008d6bc + 1;
|
|
bVar1 = 2 < DAT_8008d6bc;
|
|
|
|
*piVar5 = DAT_8008d714;
|
|
|
|
if (bVar1) {
|
|
DAT_8008d6bc = 0;
|
|
}
|
|
if (DAT_8008d6c0 < 3) {
|
|
DAT_8008d6c0 = DAT_8008d6c0 + 1;
|
|
}
|
|
|
|
// set max to zero
|
|
DAT_8008d6f4 = 0;
|
|
|
|
iVar3 = DAT_8008d6bc;
|
|
_sVar8 = DAT_8008d6c0;
|
|
if (DAT_8008d6c0 != 0) {
|
|
while (_sVar8 = _sVar8 + -1, _sVar8 != -1) {
|
|
iVar3 = iVar3 + -1;
|
|
iVar4 = iVar3 * 4;
|
|
if (iVar3 < 0) {
|
|
iVar3 = 2;
|
|
iVar4 = 8;
|
|
}
|
|
|
|
// XA_MaxSampleValInArr
|
|
if (DAT_8008d6f4 < *(int *)((int)&DAT_8008e6c8 + iVar4)) {
|
|
DAT_8008d6f4 = *(int *)((int)&DAT_8008e6c8 + iVar4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// CDSYS_XAGetNumTracks
|
|
undefined4 FUN_8001cbe0(int param_1)
|
|
|
|
{
|
|
if (
|
|
// If you are using CD instead of parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// if category is valid
|
|
(param_1 < 3)
|
|
)
|
|
{
|
|
// get number of audio tracks in this category
|
|
return *(undefined4 *)(param_1 * 4 + DAT_8008d6cc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Aug 5 calls this
|
|
// CDSYS_XASeek
|
|
// param1 - bool cdControl
|
|
// param2 - xa type (game, music, extra)
|
|
// param3 - xa audioTrackID
|
|
undefined4 FUN_8001cc18(int param_1,int param_2,int param_3)
|
|
|
|
{
|
|
undefined4 uVar1;
|
|
int iVar2;
|
|
u_char com;
|
|
CdlLOC aCStack32 [2];
|
|
|
|
// If you are using parallel port instead of CD
|
|
if (DAT_8008d6b0 == 0) {
|
|
LAB_8001cd00:
|
|
uVar1 = 1;
|
|
}
|
|
|
|
// if you are using CD instead of parallel
|
|
else
|
|
{
|
|
// bool_XnfLoaded
|
|
if (DAT_8008d6b4 != 0)
|
|
{
|
|
// three XA categories, 0,1,2
|
|
// if you go out of bounds
|
|
if (2 < param_2)
|
|
{
|
|
// quit
|
|
return 0;
|
|
}
|
|
|
|
// CDSYS_XAGetNumTracks
|
|
iVar2 = FUN_8001cbe0(param_2);
|
|
|
|
// if audioTrackID is within bounds
|
|
if (param_3 < iVar2)
|
|
{
|
|
// if stream mode is not audio
|
|
if (DAT_8008d6ac != 1)
|
|
{
|
|
// CDSYS_SetMode_StreamAudio
|
|
FUN_8001c4f4();
|
|
}
|
|
|
|
CdIntToPos
|
|
(
|
|
*(int *)
|
|
(
|
|
(uint)*(byte *)
|
|
(
|
|
DAT_8008d6e8 +
|
|
*(int *)(param_2 * 4 + DAT_8008d6d0) * 4 + param_3 * 4 + 1
|
|
) * 4 +
|
|
|
|
// XA CdPos
|
|
DAT_8008d718 +
|
|
*(int *)(param_2 * 4 + DAT_8008d71c) * 4
|
|
),
|
|
|
|
aCStack32
|
|
);
|
|
|
|
DAT_8008d708 = 1;
|
|
|
|
// CdlSeekP
|
|
// physical seek, for audio
|
|
com = '\x16';
|
|
|
|
if (param_1 != 0)
|
|
{
|
|
// CdlSeekL
|
|
// logical seek, for data
|
|
com = '\x15';
|
|
}
|
|
|
|
CdControl(com,(u_char *)aCStack32,(u_char *)0x0);
|
|
goto LAB_8001cd00;
|
|
}
|
|
}
|
|
uVar1 = 0;
|
|
}
|
|
return uVar1;
|
|
}
|
|
|
|
// CDSYS_XAGetTrackLength
|
|
// assumed to return sample length from XINF XA entry
|
|
// param1 - xa type (game, music, extra)
|
|
// param2 - xa audioTrackID
|
|
int FUN_8001cd20(int param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
if (
|
|
// if you are using CD instead of parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// bool_XnfLoaded
|
|
(DAT_8008d6b4 != 0)
|
|
)
|
|
{
|
|
// three XA categories, 0,1,2
|
|
// if you go out of bounds
|
|
if (2 < param_1) {
|
|
return 0;
|
|
}
|
|
|
|
// CDSYS_XAGetNumTracks
|
|
iVar1 = FUN_8001cbe0(param_1);
|
|
|
|
// if audioTrackID is within bounds
|
|
if (param_2 < iVar1)
|
|
{
|
|
/*
|
|
sdata->ptrArray_XaSize[
|
|
sdata->ptrArray_firstSongIndex[categoryID] +
|
|
audioTrackID
|
|
].XaBytes;
|
|
*/
|
|
return (int)*(short *)(DAT_8008d6e8 + *(int *)(param_1 * 4 + DAT_8008d6d0) * 4 + param_2 * 4 +
|
|
2);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// CDSYS_XA_TYPE_MUSIC
|
|
// 0,1,2,3 - MUSIC_RACE_INTRO
|
|
// 04 - MUSIC_RACE_WIN -- real ND name
|
|
// 05 - MUSIC_RACE_LOSE
|
|
// 06 - MUSIC_LAST_LAP -- real ND name
|
|
// 07 - MUSIC_PODIUM_POLAR_PURA
|
|
// 08 - MUSIC_PODIUM_CORTEX_NTROPY
|
|
// 09 - MUSIC_PODIUM_PENTA
|
|
// 10 - MUSIC_PODIUM_CRASH_COCO
|
|
// 11 - MUSIC_PODIUM_PINSTRIPE
|
|
// 12 - MUSIC_PODIUM_TINY
|
|
// there's probably more
|
|
|
|
// CDSYS_XA_TYPE_EXTRA
|
|
// 0x00 - 0x1e Aku Aku hints (some unused)
|
|
// 0x1e - SPEAK_AKU_39 -- real ND name
|
|
// 0x1f - 0x3c Uka Uka hints (some unused)
|
|
// 0x3d - SPEAK_UKA_39 -- real ND name
|
|
// 0x3f - SPEAK_NTROPY_BEATEN_1
|
|
// 0x40 - SPEAK_NTROPY_BEATEN_2
|
|
// 0x41 - SPEAK_NTROPY_BEATEN_3
|
|
// 0x42 - SPEAK_NTROPY_BEATEN_4
|
|
// 0x43 - SPEAK_NTROPY_UNLOCKED
|
|
// 0x44 - SPEAK_NTROPY_BEATEN_5
|
|
// 0x45 - SPEAK_NTROPY_BEATEN_6
|
|
// 0x46 - SPEAK_NTROPY_BEATEN_7
|
|
// 0x47 - SPEAK_NTROPY_BEATEN_8
|
|
|
|
// before relics
|
|
// 0x48 - SPEAK_OXIDE_RACE_INTRO_1
|
|
// 0x49 - SPEAK_OXIDE_RACE_OUTRO_1
|
|
|
|
// after relics
|
|
// 0x4a - SPEAK_OXIDE_RACE_INTRO_2
|
|
// 0x4b - SPEAK_OXIDE_RACE_OUTRO_2
|
|
|
|
// unused
|
|
// 0x4c - SPEAK_OXIDE_BRING_TROPHIES
|
|
|
|
// intro cutscene
|
|
// "greeting creatures of this planet, I come to compete..."
|
|
// 0x4d - SPEAK_OXIDE_GAME_CUTSCENE_1
|
|
// 0x4e - SPEAK_OXIDE_GAME_CUTSCENE_2
|
|
// 0x4f - SPEAK_OXIDE_GAME_CUTSCENE_3
|
|
|
|
// "start your engines for sony, fasten seatbelts for naughty dog"
|
|
// 0x50 - SPEAK_CLANCY_BROWN_SCEA_PAGE
|
|
// 0x51 - SPEAK_CLANCY_BROWN_NAUGHTY_DOG_BOX
|
|
|
|
// unused
|
|
// 0x52 - SPEAK_CLANCY_BROWN_CTR
|
|
// 0x53 - SPEAK_CLANCY_BROWN_PRESS_START_TO_PLAY
|
|
// 0x54 - SPEAK_CLANCY_BROWN_SELECT_PLAYER
|
|
// 0x55 - SPEAK_CLANCY_BROWN_SELECT_PLAYERS
|
|
// 0x56 - SPEAK_CLANCY_BROWN_CHOOSE_A_RACE_TRACK
|
|
|
|
// CDSYS_XA_TYPE_GAME
|
|
// decimal, not hex
|
|
// 0-18 - Crash
|
|
// 19-37 - Cortex
|
|
// 38-56 - Tiny
|
|
// 57-75 - Coco
|
|
// 76-94 - Ngin
|
|
// ...
|
|
// 284-303 - Oxide
|
|
// 304 - SPEAK_ROO_RACE_INTRO
|
|
// 305 - SPEAK_ROO_RACE_OUTRO
|
|
// 306 - SPEAK_ROO_RACE_INTRO_removed
|
|
// 307 - SPEAK_ROO_RACE_OUTRO_removed
|
|
// 308 - SPEAK_PAPU_RACE_INTRO
|
|
// 309 - SPEAK_PAPU_RACE_OUTRO
|
|
// 310 - SPEAK_JOE_RACE_INTRO
|
|
// 311 - SPEAK_JOE_RACE_OUTRO
|
|
// 312 - SPEAK_PSTRIPE_RACE_INTRO
|
|
// 313 - SPEAK_PSTRIPE_RACE_OUTRO
|
|
|
|
// CDSYS_XA_TYPE_WARP
|
|
// 0x00 - CRASH_SELECTED
|
|
// 0x01 - CORTEX_SELECTED
|
|
// https://www.youtube.com/watch?v=ACntd0AP6rM&t=195s
|
|
// ...
|
|
|
|
// Aug 5
|
|
// CDSYS_XAPlay
|
|
// 0 - CDSYS_XA_TYPE_MUSIC
|
|
// 1 - CDSYS_XA_TYPE_EXTRA
|
|
// 2 - CDSYS_XA_TYPE_GAME
|
|
// 3 - CDSYS_XA_TYPE_WARP -- only in prototype
|
|
undefined4 FUN_8001cdb4(int param_1,int param_2)
|
|
|
|
{
|
|
byte bVar1;
|
|
int iVar2;
|
|
undefined *puVar3;
|
|
u_char local_20;
|
|
undefined local_1f;
|
|
CdlLOC aCStack24 [2];
|
|
|
|
// If you are using parallel port instead of CD,
|
|
// which would be if you are a Naughty Dog Dev,
|
|
// and if you're reading this, you probably aren't
|
|
if (DAT_8008d6b0 == 0) {
|
|
return 1;
|
|
}
|
|
|
|
// Only continue if you are on CD
|
|
|
|
// bool_XnfLoaded
|
|
if (DAT_8008d6b4 != 0)
|
|
{
|
|
// if category is invalid
|
|
if (2 < param_1) {
|
|
return 0;
|
|
}
|
|
|
|
// CDSYS_XAGetNumTracks
|
|
iVar2 = FUN_8001cbe0(param_1);
|
|
|
|
// if index is invalid within XA category
|
|
if (iVar2 <= param_2) {
|
|
return 0;
|
|
}
|
|
|
|
// If the game is loading
|
|
if (DAT_8008d0a4 != 0)
|
|
{
|
|
// OtherFX_Play: Error sound (that's funny)
|
|
FUN_80028468(5,1);
|
|
|
|
// Sep 3
|
|
// printf("CDSYS_XAPlay failed, load_inProgress is TRUE\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
// if you get here, the game must not be loading
|
|
|
|
// if stream mode is not audio
|
|
if (DAT_8008d6ac != 1)
|
|
{
|
|
// CDSYS_SetMode_StreamAudio
|
|
FUN_8001c4f4();
|
|
}
|
|
|
|
// XA_State
|
|
DAT_8008d708 = 2;
|
|
|
|
// volume of Voice
|
|
bVar1 = DAT_8008d7bc;
|
|
if (param_1 == 0)
|
|
{
|
|
// volume of Music
|
|
bVar1 = DAT_8008d7b8;
|
|
}
|
|
|
|
// save volume
|
|
DAT_8008d70c = (uint)bVar1 << 7;
|
|
|
|
// save category and index of active XA
|
|
DAT_8008d6e0 = param_2;
|
|
DAT_8008d6e4 = param_1;
|
|
|
|
SpuSetCommonCDVolume((short)DAT_8008d70c,(short)DAT_8008d70c);
|
|
|
|
local_20 = '\x01';
|
|
puVar3 = (undefined *)(DAT_8008d6e8 + *(int *)(param_1 * 4 + DAT_8008d6d0) * 4 + param_2 * 4);
|
|
local_1f = *puVar3;
|
|
|
|
// '\r' = 0xd = CdlSetfilter
|
|
CdControl('\r',&local_20,(u_char *)0x0);
|
|
|
|
// XA StartPos
|
|
DAT_8008d6f0 =
|
|
|
|
*(int *)((uint)(byte)puVar3[1] * 4 +
|
|
|
|
// start position of each XA
|
|
*(int *)(param_1 * 4 + DAT_8008d71c) * 4 + DAT_8008d718);
|
|
|
|
// XA EndPos
|
|
DAT_8008d710 = DAT_8008d6f0 + *(short *)(puVar3 + 2);
|
|
|
|
// convert StartPosInt, to a real position
|
|
CdIntToPos(DAT_8008d6f0,aCStack24);
|
|
|
|
// XA_MaxSampleVal
|
|
DAT_8008d714 = 0;
|
|
|
|
// XA_MaxSampleValInArr
|
|
DAT_8008d6f4 = 0;
|
|
|
|
// unused
|
|
DAT_8008d700 = 0;
|
|
|
|
DAT_8008d704 = 0;
|
|
DAT_8008d724 = 0;
|
|
DAT_8008d6f8 = 0;
|
|
|
|
// countPass_CdTransferCallback
|
|
DAT_8008d6d8 = 0;
|
|
|
|
// 0x1b = CdlReadS
|
|
// set disc to XA StartPos
|
|
iVar2 = CdControl('\x1b',(u_char *)aCStack24,(u_char *)0x0);
|
|
|
|
// As of now, XA plays indefinitely, until CdReadyCallback
|
|
// determines the current CD position is past the end position,
|
|
// and then when IRQ determines the SPU is done playing the last
|
|
// of the XA, CDSYS_XAPauseForce is called to stop playing XA.
|
|
|
|
// Emulators with no IRQ support will keep playing random
|
|
// XA audio on the disc infinitely, and never reach ND Box
|
|
|
|
if (iVar2 == 1)
|
|
{
|
|
// CDSYS_SpuEnableIRQ
|
|
FUN_8001c9e4();
|
|
|
|
return 1;
|
|
}
|
|
|
|
// if it failed, assume no XA play
|
|
DAT_8008d708 = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// CDSYS_XAPauseRequest
|
|
void FUN_8001cf98(void)
|
|
|
|
{
|
|
if (
|
|
(
|
|
// If you are using CD and not parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// bool_XnfLoaded
|
|
(DAT_8008d6b4 != 0)
|
|
) &&
|
|
|
|
(
|
|
(
|
|
// if XA is playing
|
|
DAT_8008d708 == 3 ||
|
|
(DAT_8008d708 == 2)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// XA should now stop
|
|
DAT_8008d708 = 4;
|
|
|
|
// disable music
|
|
DAT_8008d6c8 = 0x400;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_XAPauseForce
|
|
void FUN_8001cfec(void)
|
|
|
|
{
|
|
if (
|
|
(
|
|
// If you are using CD and not parallel port
|
|
(DAT_8008d6b0 != 0) &&
|
|
|
|
// bool_XnfLoaded
|
|
(DAT_8008d6b4 != 0)
|
|
) &&
|
|
|
|
// if XA is playing
|
|
(DAT_8008d708 != 0)
|
|
)
|
|
{
|
|
// XA is not finished (nor started)
|
|
DAT_8008d6b8 = 0;
|
|
|
|
// As of now, no XA playing
|
|
// (exit 'start your engines' loop)
|
|
DAT_8008d708 = 0;
|
|
|
|
// cancel interrupt request
|
|
// (useless, cause it is called in CDSYS_SpuDisableIRQ anyway)
|
|
SpuSetIRQ(0);
|
|
|
|
// CDSYS_SpuDisableIRQ
|
|
FUN_8001ca64();
|
|
|
|
// '\t' = 9 = CdlPause
|
|
CdControl('\t',(u_char *)0x0,(u_char *)0x0);
|
|
|
|
// save timer, copy of frameTimer_MainFrame_ResetDB
|
|
DAT_8008d6ec = *(undefined4 *)(PTR_DAT_8008d2ac + 0x1cf8);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// CDSYS_PauseAtEnd
|
|
void FUN_8001d06c(void)
|
|
|
|
{
|
|
// if XA is finished (according to IRQ)
|
|
if (DAT_8008d6b8 != 0)
|
|
{
|
|
// CDSYS_XAPauseForce
|
|
FUN_8001cfec();
|
|
}
|
|
return;
|
|
}
|