From aa55200782eb980d7adf5af9e6a57295c795f98e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20R=C3=A1=C4=8Dek?= Date: Wed, 30 Nov 2022 23:11:58 +0100 Subject: [PATCH] Sounds, reverb, fixed image size and position --- CMakeLists.txt | 3 ++ sounds/steps.vag | Bin 0 -> 69360 bytes src/collision.c | 2 + src/display.c | 128 ++++++++++++++++++++++++++++++++--------------- src/input.c | 39 +++++++++++---- src/input.h | 1 + src/main.c | 52 ++++++++++++++++++- src/options.h | 8 +-- src/sound.c | 93 ++++++++++++++++++++++++++++++++++ src/sound.h | 60 ++++++++++++++++++++++ 10 files changed, 332 insertions(+), 54 deletions(-) create mode 100644 sounds/steps.vag create mode 100644 src/sound.c create mode 100644 src/sound.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f0560b5..35c38a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,11 +21,14 @@ psn00bsdk_add_executable(horror STATIC src/texture.c src/input.c src/collision.c + src/sound.c ) psn00bsdk_target_incbin(horror PRIVATE bandwidth_face textures/bandwidth_face.tim) psn00bsdk_target_incbin(horror PRIVATE duch textures/duch.tim) +psn00bsdk_target_incbin(horror PRIVATE steps sounds/steps.vag) + foreach(TEXTURE ${TEXTURES}) get_filename_component(BARENAME ${TEXTURE} NAME) string(REGEX REPLACE "\\.[^.]*$" "" TEXTURE_NAME ${BARENAME}) diff --git a/sounds/steps.vag b/sounds/steps.vag new file mode 100644 index 0000000000000000000000000000000000000000..c7e5bb3155dbec14b6401f8a8bf7ea987ab9637f GIT binary patch literal 69360 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 topLeft.vz) { diff --git a/src/display.c b/src/display.c index 85d4efc..88458d9 100644 --- a/src/display.c +++ b/src/display.c @@ -23,28 +23,77 @@ void initDisplay(void) { ResetGraph(0); - // Setup DB 0 - SetDefDispEnv(&db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES); - SetDefDrawEnv(&db[0].draw, 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); + if (GetVideoMode() == MODE_NTSC) + { + SetDefDispEnv(&db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES_NTSC); + SetDefDrawEnv(&db[0].draw, 0, SCREEN_YRES_NTSC, SCREEN_XRES, SCREEN_YRES_NTSC); + } + else + { + SetDefDispEnv(&db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES_PAL); + SetDefDrawEnv(&db[0].draw, 0, SCREEN_YRES_PAL, SCREEN_XRES, SCREEN_YRES_PAL); + db[0].disp.screen.y = 20; + db[0].disp.screen.h = 256; + } setRGB0(&db[0].draw, 0, 0, 0); db[0].draw.isbg = 1; db[0].draw.dtd = 1; - // Setup DB 1 - SetDefDispEnv(&db[1].disp, 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); - SetDefDrawEnv(&db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES); + if (GetVideoMode() == MODE_NTSC) + { + SetDefDispEnv(&db[1].disp, 0, SCREEN_YRES_NTSC, SCREEN_XRES, SCREEN_YRES_NTSC); + SetDefDrawEnv(&db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES_NTSC); + } + else + { + SetDefDispEnv(&db[1].disp, 0, SCREEN_YRES_PAL, SCREEN_XRES, SCREEN_YRES_PAL); + SetDefDrawEnv(&db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES_PAL); + db[1].disp.screen.y = 20; + db[1].disp.screen.h = 256; + } setRGB0(&db[1].draw, 0, 0, 0); db[1].draw.isbg = 1; db[1].draw.dtd = 1; - setRECT(&screen_clip, 0, 0, SCREEN_XRES, SCREEN_YRES); - - InitGeom(); - gte_SetGeomOffset(CENTERX, CENTERY); + if (GetVideoMode() == MODE_NTSC) + { + setRECT(&screen_clip, 0, 0, SCREEN_XRES, SCREEN_YRES_NTSC); + InitGeom(); + gte_SetGeomOffset(CENTERX, CENTERY_NTSC); + } + else + { + setRECT(&screen_clip, 0, 0, SCREEN_XRES, SCREEN_YRES_PAL); + InitGeom(); + gte_SetGeomOffset(CENTERX, CENTERY_PAL); + } gte_SetGeomScreen(CENTERX); + + /* + // Setup DB 0 + SetDefDispEnv(&db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES); + SetDefDrawEnv(&db[0].draw, 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); + + setRGB0(&db[0].draw, 0, 0, 0); + db[0].draw.isbg = 1; + db[0].draw.dtd = 1; + + // Setup DB 1 + SetDefDispEnv(&db[1].disp, 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES); + SetDefDrawEnv(&db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES); + + setRGB0(&db[1].draw, 0, 0, 0); + db[1].draw.isbg = 1; + db[1].draw.dtd = 1; + setRECT(&screen_clip, 0, 0, SCREEN_XRES, SCREEN_YRES); + + + gte_SetGeomOffset(CENTERX, CENTERY); + gte_SetGeomScreen(CENTERX); + */ gte_SetBackColor(0, 0, 0); #ifdef LOAD_FONT @@ -127,7 +176,6 @@ void sortObject(OBJECT *obj) v_dir.vy = l_point.vy - obj->pos.vy - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v2].vy; v_dir.vz = l_point.vz - obj->pos.vz - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v2].vz; - gte_ldv3(&obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v0], &obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v1], &obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v2]); @@ -142,7 +190,7 @@ void sortObject(OBJECT *obj) // Skip drawing this quad if the first 3 vertices are aligned (p = 0) // or in counterclockwise (p < 0) order. - if(p >= 0) + if (p >= 0) continue; gte_stsxy3(&pol4->x0, &pol4->x1, &pol4->x2); @@ -155,9 +203,8 @@ void sortObject(OBJECT *obj) gte_avsz4(); gte_stotz(&p); - if( (p>>2) >= OT_LEN ) - continue; - + if ((p >> 2) >= OT_LEN) + continue; gte_stsxy(&pol4->x3); @@ -165,17 +212,16 @@ void sortObject(OBJECT *obj) gte_ldrgb(&pol4->r0); gte_ldv0(&obj->mesh.normal_data[(obj->mesh.normal_indices[i]).v0]); - v_dir.vx = l_point.vx - obj->pos.vx - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v0].vx; v_dir.vy = l_point.vy - obj->pos.vy - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v0].vy; v_dir.vz = l_point.vz - obj->pos.vz - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v0].vz; - intensity = 4096*4 - (( - (v_dir.vx * v_dir.vx) + - (v_dir.vy * v_dir.vy) + - (v_dir.vz * v_dir.vz)) >> - 7); + intensity = 4096 * 4 - (( + (v_dir.vx * v_dir.vx) + + (v_dir.vy * v_dir.vy) + + (v_dir.vz * v_dir.vz)) >> + 7); if (intensity < 0) intensity = 0; @@ -198,11 +244,11 @@ void sortObject(OBJECT *obj) v_dir.vy = l_point.vy - obj->pos.vy - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v1].vy; v_dir.vz = l_point.vz - obj->pos.vz - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v1].vz; - intensity = 4096*4 - (( - (v_dir.vx * v_dir.vx) + - (v_dir.vy * v_dir.vy) + - (v_dir.vz * v_dir.vz)) >> - 7); + intensity = 4096 * 4 - (( + (v_dir.vx * v_dir.vx) + + (v_dir.vy * v_dir.vy) + + (v_dir.vz * v_dir.vz)) >> + 7); if (intensity < 0) intensity = 0; @@ -228,11 +274,11 @@ void sortObject(OBJECT *obj) v_dir.vy = l_point.vy - obj->pos.vy - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v2].vy; v_dir.vz = l_point.vz - obj->pos.vz - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v2].vz; - intensity = 4096*4 - (( - (v_dir.vx * v_dir.vx) + - (v_dir.vy * v_dir.vy) + - (v_dir.vz * v_dir.vz)) >> - 7); + intensity = 4096 * 4 - (( + (v_dir.vx * v_dir.vx) + + (v_dir.vy * v_dir.vy) + + (v_dir.vz * v_dir.vz)) >> + 7); if (intensity < 0) intensity = 0; @@ -258,11 +304,11 @@ void sortObject(OBJECT *obj) v_dir.vy = l_point.vy - obj->pos.vy - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v3].vy; v_dir.vz = l_point.vz - obj->pos.vz - obj->mesh.vertex_data[obj->mesh.vertex_indices[i].v3].vz; - intensity = 4096*4 - (( - (v_dir.vx * v_dir.vx) + - (v_dir.vy * v_dir.vy) + - (v_dir.vz * v_dir.vz)) >> - 7); + intensity = 4096 * 4 - (( + (v_dir.vx * v_dir.vx) + + (v_dir.vy * v_dir.vy) + + (v_dir.vz * v_dir.vz)) >> + 7); if (intensity < 0) intensity = 0; @@ -285,10 +331,10 @@ void sortObject(OBJECT *obj) gte_nccs(); setUV4(pol4, - obj->mesh.uv_data[obj->mesh.uv_indices[i].v0].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v0].vy , - obj->mesh.uv_data[obj->mesh.uv_indices[i].v1].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v1].vy , - obj->mesh.uv_data[obj->mesh.uv_indices[i].v2].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v2].vy , - obj->mesh.uv_data[obj->mesh.uv_indices[i].v3].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v3].vy ); + obj->mesh.uv_data[obj->mesh.uv_indices[i].v0].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v0].vy, + obj->mesh.uv_data[obj->mesh.uv_indices[i].v1].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v1].vy, + obj->mesh.uv_data[obj->mesh.uv_indices[i].v2].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v2].vy, + obj->mesh.uv_data[obj->mesh.uv_indices[i].v3].vx, obj->texture.texture_size - 1 - obj->mesh.uv_data[obj->mesh.uv_indices[i].v3].vy); pol4->tpage = getTPage(obj->texture.tim.mode, 0, obj->texture.tim.prect->x, obj->texture.tim.prect->y); @@ -299,7 +345,7 @@ void sortObject(OBJECT *obj) addPrim(&(db[db_active].ot)[p >> 2], pol4); pol4++; - //if (pol4 >= (db_nextpri + PACKET_LEN)) + // if (pol4 >= (db_nextpri + PACKET_LEN)) // break; } } diff --git a/src/input.c b/src/input.c index b97fb0e..8245383 100644 --- a/src/input.c +++ b/src/input.c @@ -5,12 +5,15 @@ SVECTOR trot; VECTOR camPosOld; -VECTOR cam_pos = {0, -600 << 12, 0};; -VECTOR cam_rot; +VECTOR cam_pos = {-350 << 12, -600 << 12, 0}; +; +VECTOR cam_rot = {0, 1024 << 12, 0}; PADTYPE *pad; uint8_t padBuffer[2][34]; +int movesPrev = 1; + void initInput(void) { InitPAD(padBuffer[0], 34, padBuffer[1], 34); @@ -31,8 +34,11 @@ void pollInput(int deltaTime) tpos.vy = -cam_pos.vy >> 12; tpos.vz = -cam_pos.vz >> 12; + int moves = 0; + VECTOR positon = getCamPosWorld(); - if(!isPlayerOnMesh(&positon)) { + if (!isPlayerOnMesh(&positon)) + { cam_pos = camPosOld; } @@ -86,14 +92,15 @@ void pollInput(int deltaTime) // Move forward cam_pos.vx -= deltaTime * isin(trot.vy) << 4; cam_pos.vz += deltaTime * icos(trot.vy) << 4; + moves = 1; } else if (!(pad->btn & PAD_CROSS)) { // Move backward - cam_pos.vx += deltaTime * ((isin(trot.vy) * icos(trot.vx)) >> 12) << 4; - cam_pos.vy -= deltaTime * isin(trot.vx) << 4; - cam_pos.vz -= deltaTime * ((icos(trot.vy) * icos(trot.vx)) >> 12) << 4; + cam_pos.vx += deltaTime * isin(trot.vy) << 4; + cam_pos.vz -= deltaTime * icos(trot.vy) << 4; + moves = 1; } if (!(pad->btn & PAD_SQUARE)) @@ -102,6 +109,7 @@ void pollInput(int deltaTime) // Slide left cam_pos.vx -= deltaTime * icos(trot.vy) << 4; cam_pos.vz -= deltaTime * isin(trot.vy) << 4; + moves = 1; } else if (!(pad->btn & PAD_CIRCLE)) { @@ -109,6 +117,7 @@ void pollInput(int deltaTime) // Slide right cam_pos.vx += deltaTime * icos(trot.vy) << 4; cam_pos.vz += deltaTime * isin(trot.vy) << 4; + moves = 1; } } @@ -121,10 +130,12 @@ void pollInput(int deltaTime) { cam_pos.vx += deltaTime * - (((isin(trot.vy) * icos(trot.vx)) >> 12) * (pad->ls_y - 128)) >> 5; + (((isin(trot.vy) * icos(trot.vx)) >> 12) * (pad->ls_y - 128)) >> + 5; cam_pos.vy -= deltaTime * (isin(trot.vx) * (pad->ls_y - 128)) >> 5; cam_pos.vz -= deltaTime * - (((icos(trot.vy) * icos(trot.vx)) >> 12) * (pad->ls_y - 128)) >> 5; + (((icos(trot.vy) * icos(trot.vx)) >> 12) * (pad->ls_y - 128)) >> + 5; } // Strafing left and right @@ -146,6 +157,16 @@ void pollInput(int deltaTime) cam_rot.vy -= deltaTime * (pad->rs_x - 128) << 9; } } + if (moves == 1 && movesPrev == 0) + { + SpuSetKey(1, 1 << 0); + movesPrev = 1; + } + else if(moves == 0 && movesPrev == 1) + { + SpuSetKey(0, 1 << 0); + movesPrev = 0; + } } } @@ -154,7 +175,7 @@ VECTOR *getCamPos(void) return &tpos; } -VECTOR getCamPosWorld(void) +VECTOR getCamPosWorld(void) { VECTOR negCamPos = {-tpos.vx, -tpos.vy, -tpos.vz}; negCamPos.vx = cam_pos.vx >> 12; diff --git a/src/input.h b/src/input.h index 54d5288..0f18b13 100644 --- a/src/input.h +++ b/src/input.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include "collision.h" diff --git a/src/main.c b/src/main.c index dd98b4b..5ae903c 100644 --- a/src/main.c +++ b/src/main.c @@ -2,10 +2,12 @@ #include #include #include +#include #include "display.h" #include "texture.h" #include "input.h" +#include "sound.h" #include "../meshes/cube.c" #include "../meshes/maze.c" @@ -14,6 +16,8 @@ extern const uint32_t bandwidth_face[]; extern const uint32_t duch[]; +extern const uint32_t steps[]; + int i = 0; int p_ang = 0; @@ -25,6 +29,9 @@ VECTOR duchPos = {-1000, -400, 5216}; SVECTOR cubeRot = {0, 0, 0}; VECTOR light_point; +int steps_addr; +int steps_sr; + void gameInit() { loadTexture(bandwidth_face, &cube.texture); @@ -41,13 +48,54 @@ void gameInit() maze.texture.texture_size = 128; cube.rot = cubeRot; + + VAG_Header *steps_vag = (VAG_Header *) steps; + steps_addr = upload_sample(&steps_vag[1], SWAP_ENDIAN(steps_vag->size)); + steps_sr = SWAP_ENDIAN(steps_vag->sample_rate); + int ch = play_sample(steps_addr, steps_sr); + + ReverbPreset rp; + + rp.dAPF1 = 0x01A5; + rp.dAPF2 = 0x0139; + rp.vIIR = 0x6000; + rp.vCOMB1 = 0x5000; + rp.vCOMB2 = 0x4c00; + rp.vCOMB3 = 0xB800; + rp.vCOMB4 = 0xBC00; + rp.vWALL = 0xc000; + rp.vAPF1 = 0x6000; + rp.vAPF2 = 0x5C00; + rp.mLSAME = 0x15BA; + rp.mRSAME = 0x11BB; + rp.mLCOMB1 = 0x14C2; + rp.mRCOMB1 = 0x10BD; + rp.mLCOMB2 = 0x11BC; + rp.mRCOMB2 = 0x0dc1; + rp.dLSAME = 0x11c0; + rp.dRSAME = 0x0dc3; + rp.mLDIFF = 0x0dc0; + rp.mRDIFF = 0x09c1; + rp.mLCOMB3 = 0x0bc4; + rp.mRCOMB3 = 0x07c1; + rp.mLCOMB4 = 0x0a00; + rp.mRCOMB4 = 0x06cd; + rp.dLDIFF = 0x09c2; + rp.dRDIFF = 0x05c1; + rp.mLAPF1 = 0x05c0; + rp.mRAPF1 = 0x041a; + rp.mLAPF2 = 0x0274; + rp.mRAPF2 = 0x013a; + rp.vLIN = 0x8000; + rp.vRIN = 0x8000; + setupReverb(0x7ffe, 0xade0 , &rp); + enableReverbOnChannels(1 << 0); } void gameLoop() { setVector(&light_point, (icos(p_ang) >> 2) >> 2, -350, (isin(p_ang) >> 2) >> 2); p_ang += 16; - setLightPosition(getCamPosWorld()); FntPrint(-1, "Cube: %d %d %d\n", cube.pos.vx, cube.pos.vy, cube.pos.vz); @@ -66,6 +114,8 @@ int deltaTime; int main(int argc, const char *argv[]) { initDisplay(); + SpuInit(); + initInput(); gameInit(); setGameLoopCallback(&gameLoop); diff --git a/src/options.h b/src/options.h index 4c8efc7..6df61cf 100644 --- a/src/options.h +++ b/src/options.h @@ -11,10 +11,12 @@ changing common variables like screen resolution */ #define OT_LEN 4096*4 #define PACKET_LEN 16384*4 -#define SCREEN_XRES 320 -#define SCREEN_YRES 240 +#define SCREEN_XRES 320 +#define SCREEN_YRES_NTSC 240 +#define SCREEN_YRES_PAL 256 #define CENTERX (SCREEN_XRES / 2) -#define CENTERY (SCREEN_YRES / 2) +#define CENTERY_NTSC (SCREEN_YRES_NTSC / 2) +#define CENTERY_PAL (SCREEN_YRES_PAL / 2) typedef POLY_GT4 QUAD; diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..6b71c3c --- /dev/null +++ b/src/sound.c @@ -0,0 +1,93 @@ +#include "sound.h" +#define ALLOC_START_ADDR 0x1010 +#define SPU_REVERB_REGS ((volatile uint16_t *) (IOBASE | 0x1dc0)) + +#define getADSR1(attackMode, attackShift, attackStep, decayShift, sustainLevel) \ + (((attackMode) << 15) | ((attackShift) << 10) | ((attackStep) << 8) | ((decayShift) << 4) | (sustainLevel)) +#define getADSR2(sustainMode, sustainDir, sustainShift, sustainStep, releaseMode, releaseShift) \ + (((sustainMode) << 15) | ((sustainDir) << 14) | ((sustainShift) << 8) | ((sustainStep) << 6) | ((releaseMode) << 5) | (releaseShift)) + +static int next_sample_addr = ALLOC_START_ADDR; +static int next_channel = 0; + +int upload_sample(const void *data, int size) +{ + // Round the size up to the nearest multiple of 64, as SPU DMA transfers + // are done in 64-byte blocks. + int _addr = next_sample_addr; + int _size = (size + 63) & 0xffffffc0; + + SpuSetTransferMode(SPU_TRANSFER_BY_DMA); + SpuSetTransferStartAddr(_addr); + + SpuWrite((const uint32_t *)data, _size); + SpuIsTransferCompleted(SPU_TRANSFER_WAIT); + + next_sample_addr = _addr + _size; + return _addr; +} + +int play_sample(int addr, int sample_rate) +{ + int ch = next_channel; + + // Make sure the channel is stopped. + SpuSetKey(0, 1 << ch); + + // Set the channel's sample rate and start address. Note that the SPU + // expects the sample rate to be in 4.12 fixed point format (with + // 1.0 = 44100 Hz) and the address in 8-byte units; psxspu.h provides the + // getSPUSampleRate() and getSPUAddr() macros to convert values to these + // units. + SPU_CH_FREQ(ch) = getSPUSampleRate(sample_rate); + SPU_CH_ADDR(ch) = getSPUAddr(addr); + + // Set the channel's volume and ADSR parameters (0x80ff and 0x1fee are + // dummy values that disable the ADSR envelope entirely). + SPU_CH_VOL_L(ch) = 0x3fff; + SPU_CH_VOL_R(ch) = 0x3fff; + SPU_CH_ADSR1(ch) = getADSR1(0, 0, 0, 15, 15); + SPU_CH_ADSR2(ch) = getADSR2(0, 0, 0, 0, 0, 0); + + // Start the channel. + SpuSetKey(1, 1 << ch); + + next_channel = (ch + 1) % 24; + return ch; +} + + +// Volume must be in 0x0000-0x7fff range. +// Buffer size must be a multiple of 16 bytes and >= 16. +void setupReverb(int volume, int bufferSize, const ReverbPreset *preset) { + const uint16_t *_preset = (const uint16_t *) preset; + // This must be done 16 bits at a time, not 8 or 32. + for (int i = 0; i < (sizeof(ReverbPreset) / 2); i++) + SPU_REVERB_REGS[i] = _preset[i]; + + SPU_REVERB_VOL_L = (uint16_t) volume; + SPU_REVERB_VOL_R = (uint16_t) volume; + SpuSetReverbAddr(0x80000 - bufferSize); + + SPU_CTRL |= 1 << 7; +} + +void disableReverb(void) { + SPU_CTRL &= ~(1 << 7); + + SPU_REVERB_VOL_L = 0; + SPU_REVERB_VOL_R = 0; + SpuSetReverbAddr(0x7fff0); +} + +void enableReverbOnChannels(uint32_t bits) { + SPU_REVERB_ON1 = (uint16_t) bits; + SPU_REVERB_ON2 = (uint16_t) (bits >> 16); +} + +void enableReverbOnCDAudio(int enable) { + if (enable) + SPU_CTRL |= 1 << 2; + else + SPU_CTRL &= ~(1 << 2); +} \ No newline at end of file diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000..54a40da --- /dev/null +++ b/src/sound.h @@ -0,0 +1,60 @@ +#include +#include +#include + +typedef struct { + uint32_t magic; // 0x70474156 ("VAGp") for mono files + uint32_t version; + uint32_t interleave; // Unused in mono files + uint32_t size; // Big-endian, in bytes + uint32_t sample_rate; // Big-endian, in Hertz + uint32_t _reserved[3]; + char name[16]; +} VAG_Header; + +typedef struct { + uint16_t dAPF1; // Reverb APF Offset 1 + uint16_t dAPF2; // Reverb APF Offset 2 + uint16_t vIIR; // Reverb Reflection Volume 1 + uint16_t vCOMB1; // Reverb Comb Volume 1 + uint16_t vCOMB2; // Reverb Comb Volume 2 + uint16_t vCOMB3; // Reverb Comb Volume 3 + uint16_t vCOMB4; // Reverb Comb Volume 4 + uint16_t vWALL; // Reverb Reflection Volume 2 + uint16_t vAPF1; // Reverb APF Volume 1 + uint16_t vAPF2; // Reverb APF Volume 2 + uint16_t mLSAME; // Reverb Same Side Reflection Address 1 Left + uint16_t mRSAME; // Reverb Same Side Reflection Address 1 Right + uint16_t mLCOMB1; // Reverb Comb Address 1 Left + uint16_t mRCOMB1; // Reverb Comb Address 1 Right + uint16_t mLCOMB2; // Reverb Comb Address 2 Left + uint16_t mRCOMB2; // Reverb Comb Address 2 Right + uint16_t dLSAME; // Reverb Same Side Reflection Address 2 Left + uint16_t dRSAME; // Reverb Same Side Reflection Address 2 Right + uint16_t mLDIFF; // Reverb Different Side Reflect Address 1 Left + uint16_t mRDIFF; // Reverb Different Side Reflect Address 1 Right + uint16_t mLCOMB3; // Reverb Comb Address 3 Left + uint16_t mRCOMB3; // Reverb Comb Address 3 Right + uint16_t mLCOMB4; // Reverb Comb Address 4 Left + uint16_t mRCOMB4; // Reverb Comb Address 4 Right + uint16_t dLDIFF; // Reverb Different Side Reflect Address 2 Left + uint16_t dRDIFF; // Reverb Different Side Reflect Address 2 Right + uint16_t mLAPF1; // Reverb APF Address 1 Left + uint16_t mRAPF1; // Reverb APF Address 1 Right + uint16_t mLAPF2; // Reverb APF Address 2 Left + uint16_t mRAPF2; // Reverb APF Address 2 Right + uint16_t vLIN; // Reverb Input Volume Left + uint16_t vRIN; // Reverb Input Volume Right +} ReverbPreset; + +#define SWAP_ENDIAN(x) ( \ + (((uint32_t) (x) & 0x000000ff) << 24) | \ + (((uint32_t) (x) & 0x0000ff00) << 8) | \ + (((uint32_t) (x) & 0x00ff0000) >> 8) | \ + (((uint32_t) (x) & 0xff000000) >> 24) \ +) + +int upload_sample(const void *data, int size); +int play_sample(int addr, int sample_rate); +void setupReverb(int volume, int bufferSize, const ReverbPreset *preset); +void enableReverbOnChannels(uint32_t bits);