diff --git a/Makefile b/Makefile
index fe7ceb1..e88b4b7 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ src/physics.c \
src/graphics.c \
src/psx.c \
src/space.c \
+src/sound.c \
levels/level0.c \
levels/level1.c \
TIM/home.tim \
diff --git a/config/OverlayExample.xml b/config/OverlayExample.xml
index 6f69d7e..13a70ab 100644
--- a/config/OverlayExample.xml
+++ b/config/OverlayExample.xml
@@ -16,6 +16,8 @@
+
+
diff --git a/include/psx.h b/include/psx.h
index 5399d67..5a8d158 100644
--- a/include/psx.h
+++ b/include/psx.h
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/include/sound.h b/include/sound.h
new file mode 100644
index 0000000..c6367ac
--- /dev/null
+++ b/include/sound.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "../include/psx.h"
+
+#define CD_SECTOR_SIZE 2048
+// XA
+// Sector offset for XA data 4: simple speed, 8: double speed
+#define XA_SECTOR_OFFSET 4
+// Number of XA files
+#define XA_TRACKS 1
+// Number of populated XA streams/channels in each XA file
+#define INDEXES_IN_XA 1
+#define TOTAL_TRACKS (XA_TRACKS*INDEXES_IN_XA)
+
+// XA track struc
+typedef struct {
+ int start;
+ int end;
+} XA_TRACK;
+
+void setSPUsettings(SpuCommonAttr * spuSettings);
+int prepareXAplayback(CdlFILTER * filter, char * channel);
+int resetXAsettings(void);
+void loadXAfile( char * XAfile, XA_TRACK * XATrack);
+u_char startXAPlayback(int * sectorPos, CdlLOC * loc);
+int stopXAPlayback(void);
+int setXAchannel(CdlFILTER * filter, char * channel);
+int playXAtrack(int * CurPos, XA_TRACK * XATrack, CdlFILTER * filter, CdlLOC * loc, char * channel);
diff --git a/src/main.c b/src/main.c
index bbe9f3a..f670df2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -24,6 +24,7 @@
#include "../include/physics.h"
#include "../include/graphics.h"
#include "../include/space.h"
+#include "../include/sound.h"
#define USECD
@@ -105,6 +106,28 @@ VECTOR col = {0};
short timediv = 1;
// Animation time, see l.206
int atime = 0;
+// Sound
+// SPU attributes
+SpuCommonAttr spuSettings;
+// Declare an array of XA_TRACK
+XA_TRACK XATrack[XA_TRACKS];
+// Name of file to load
+static char * loadXA = "\\INTER8.XA;1";
+// ADPCM Filter
+CdlFILTER filter;
+// Position of file on CD
+CdlLOC loc;
+// XA settings
+u_char param[4];
+// Start and end position of XA data, in sectors
+//~ static int StartPos, EndPos;
+// Current pos in file
+static int CurPos = -1;
+// Playback status : 0 not playing, 1 playing
+//~ static int gPlaying = 0;
+// Current XA channel
+static char channel = 0;
+
int main() {
// Set matrices pointers to scratchpad
camera.mat = dc_camMat;
@@ -175,9 +198,19 @@ int main() {
setCameraPos(&camera, &curLvl.camPtr->campos->pos, &curLvl.camPtr->campos->rot);
// Time counter
oldTime = GetRCnt(RCntCNT1);
+ // Sound
+ setSPUsettings(&spuSettings);
+ #ifdef USECD
+ loadXAfile(loadXA, XATrack);
+ #endif
+ prepareXAplayback(&filter, &channel);
+ CurPos = XATrack[0].start;
// Main loop
while ( VSync(VSYNC) ) {
+ // Sound playback
+ playXAtrack(&CurPos, XATrack, &filter, &loc, &channel);
+
dt = GetRCnt(RCntCNT1) - oldTime;
oldTime = GetRCnt(RCntCNT1);
@@ -265,11 +298,28 @@ int main() {
}
// Physics
if ( physics ) {
+ u_char canMove = 1;
for ( int k = 0; k < *curLvl.meshes_length; k ++ ) {
if ( curLvl.meshes[k]->isRigidBody == 1 ) {
applyAcceleration( curLvl.meshes[k]->body, dt);
+ // Get col between props and level
+ if ( curLvl.meshes[k]->isProp ){
+ checkBodyCol( curLvl.meshes[k]->body , curLvl.meshes[k]->node->plane->body );
+ for (short obj=0; obj < curLvl.curNode->objects->index; obj++){
+ // If isWall, check collision
+ if ( curLvl.curNode->objects->list[obj]->isWall ){
+ if( getExtCollision( *curLvl.meshes[k]->body, *curLvl.curNode->objects->list[obj]->body ).vz &&
+ getExtCollision( *curLvl.meshes[k]->body, *curLvl.curNode->objects->list[obj]->body ).vx) {
+ curLvl.meshes[k]->body->position.vz = curLvl.meshes[k]->body->position.vz - curLvl.meshes[k]->body->velocity.vz ;
+ curLvl.meshes[k]->body->position.vx = curLvl.meshes[k]->body->position.vx - curLvl.meshes[k]->body->velocity.vx ;
+ canMove = 0;
+ }
+ }
+ }
+ }
+ // Get col between actor and level
if ( curLvl.meshes[k]->isActor ){
- // Get col between actor and level
+ // Check col
checkBodyCol( curLvl.meshes[k]->body , curLvl.levelPtr->body );
// Get col between actor and current node's walls
// Loop on current node's objects
@@ -284,15 +334,12 @@ int main() {
}
}
}
- // Get col between props and level
- if ( curLvl.meshes[k]->isProp ){
- checkBodyCol( curLvl.meshes[k]->body , curLvl.meshes[k]->node->plane->body );
- }
+
// Only evaluate collision if actor is on same plane as prop
if ( curLvl.curNode == curLvl.propPtr->node ){
// Get col between actor and props
col = getExtCollision( *curLvl.meshes[k]->body, *curLvl.propPtr->body );
- if (col.vx && col.vz ) {
+ if (col.vx && col.vz && canMove == 1 ) {
setVector( &curLvl.propPtr->body->velocity,
curLvl.meshes[k]->body->velocity.vx,
0,
diff --git a/src/psx.c b/src/psx.c
index 62fc198..cbb4b87 100644
--- a/src/psx.c
+++ b/src/psx.c
@@ -25,6 +25,8 @@ void init(DISPENV disp[2], DRAWENV draw[2], short db, CVECTOR * BGc, VECTOR * BK
//~ PadInit(0);
//~ InitPAD(controllers[0].pad, 34, controllers[1].pad, 34);
//~ StartPAD();
+ // Init SPU
+ SpuInit();
// Reset the GPU
ResetGraph( 0 );
// Initialize and setup the GTE
diff --git a/src/sound.c b/src/sound.c
new file mode 100644
index 0000000..37b3bcc
--- /dev/null
+++ b/src/sound.c
@@ -0,0 +1,82 @@
+#include "../include/sound.h"
+#include "../include/space.h"
+
+void setSPUsettings(SpuCommonAttr * spuSettings){
+ // Set master & CD volume to max
+ spuSettings->mask = (SPU_COMMON_MVOLL | SPU_COMMON_MVOLR | SPU_COMMON_CDVOLL | SPU_COMMON_CDVOLR | SPU_COMMON_CDMIX);
+ spuSettings->mvol.left = 0x6000;
+ spuSettings->mvol.right = 0x6000;
+ spuSettings->cd.volume.left = 0x6000;
+ spuSettings->cd.volume.right = 0x6000;
+ // Enable CD input ON
+ spuSettings->cd.mix = SPU_ON;
+ // Apply settings
+ SpuSetCommonAttr(spuSettings);
+ // Set transfer mode
+ SpuSetTransferMode(SPU_TRANSFER_BY_DMA);
+}
+
+int resetXAsettings(void){
+ // Reset parameters
+ u_char param = CdlModeSpeed;
+ // Set CD mode
+ return CdControlB(CdlSetmode, ¶m, 0);
+}
+int prepareXAplayback(CdlFILTER * filter, char * channel){
+ u_char param = CdlModeSpeed|CdlModeRT|CdlModeSF|CdlModeSize1;
+ // Set the parameters above
+ CdControlB(CdlSetmode, ¶m, 0);
+ // Pause at current pos
+ CdControlF(CdlPause,0);
+ // Set filter
+ // Use file 1, channel 0
+ filter->file = 1;
+ filter->chan = *channel;
+ return CdControlF(CdlSetfilter, (u_char *)filter);
+}
+void loadXAfile( char * XAfile, XA_TRACK * XATrack){
+ CdlFILE XAPos;
+ CdSearchFile( &XAPos, XAfile);
+ XATrack[0].start = CdPosToInt(&XAPos.pos);
+ XATrack[0].end = XATrack[0].start + (XAPos.size/CD_SECTOR_SIZE) - 1;
+}
+
+u_char startXAPlayback(int * sectorPos, CdlLOC * loc){
+ // Convert sector number to CD position in min/second/frame and set CdlLOC accordingly.
+ CdIntToPos( *sectorPos, loc);
+ // Send CDROM read command
+ CdControlF(CdlReadS, (u_char *)loc);
+ return 1;
+}
+int stopXAPlayback(void){
+ // stop CD
+ return CdControlF(CdlStop,0);
+}
+int setXAchannel(CdlFILTER * filter, char * channel){
+ filter->chan = *channel;
+ // Set filter
+ return CdControlF(CdlSetfilter, (u_char *)filter);
+}
+int playXAtrack(int * CurPos, XA_TRACK * XATrack, CdlFILTER * filter, CdlLOC * loc, char * channel){
+ static int gPlaying = 0;
+ // Sound playback
+ // Begin XA file playback
+ if (gPlaying == 0 && *CurPos == XATrack[0].start){
+ gPlaying = startXAPlayback(&XATrack[0].start, loc);
+ }
+ // When endPos is reached, set playing flag to 0
+ if ((*CurPos += XA_SECTOR_OFFSET) >= XATrack[0].end){
+ gPlaying = 0;
+ }
+ // If XA file end is reached, stop playback
+ if ( gPlaying == 0 && *CurPos >= XATrack[0].end ){
+ // Stop CD playback
+ stopXAPlayback();
+ // Optional
+ //~ resetXAsettings();
+ // Switch to next channel and start play back
+ *channel = !*channel;
+ setXAchannel(filter, channel);
+ *CurPos = XATrack[0].start;
+ }
+}
diff --git a/xa/inter8.xa b/xa/inter8.xa
new file mode 100644
index 0000000..5ea675f
Binary files /dev/null and b/xa/inter8.xa differ