From 1daa9a7a849b6b442d8d16ac3a798f50c8a15ce9 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Mon, 1 Dec 2025 09:02:18 -0600 Subject: [PATCH 1/3] add: Implementation of sdhd module --- iop/sound/sdhd/Makefile | 20 + iop/sound/sdhd/README.md | 15 + iop/sound/sdhd/include/sdhd.h | 425 +++++++++ iop/sound/sdhd/src/exports.tab | 56 ++ iop/sound/sdhd/src/imports.lst | 10 + iop/sound/sdhd/src/irx_imports.h | 23 + iop/sound/sdhd/src/sdhd.c | 1534 ++++++++++++++++++++++++++++++ 7 files changed, 2083 insertions(+) create mode 100644 iop/sound/sdhd/Makefile create mode 100644 iop/sound/sdhd/README.md create mode 100644 iop/sound/sdhd/include/sdhd.h create mode 100644 iop/sound/sdhd/src/exports.tab create mode 100644 iop/sound/sdhd/src/imports.lst create mode 100644 iop/sound/sdhd/src/irx_imports.h create mode 100644 iop/sound/sdhd/src/sdhd.c diff --git a/iop/sound/sdhd/Makefile b/iop/sound/sdhd/Makefile new file mode 100644 index 000000000000..4a31649576ed --- /dev/null +++ b/iop/sound/sdhd/Makefile @@ -0,0 +1,20 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN ?= sdhd.irx + +IOP_IMPORT_INCS += \ + system/intrman \ + system/loadcore + +IOP_OBJS = sdhd.o exports.o imports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/sound/sdhd/README.md b/iop/sound/sdhd/README.md new file mode 100644 index 000000000000..d7e1e2cd539f --- /dev/null +++ b/iop/sound/sdhd/README.md @@ -0,0 +1,15 @@ +# Sound data (HD file) access library + +This module provides functions to access sound banks stored in HD files. + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `sdhd` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, use `LoadModule` or \ +`LoadModuleBuffer` with no arguments. diff --git a/iop/sound/sdhd/include/sdhd.h b/iop/sound/sdhd/include/sdhd.h new file mode 100644 index 000000000000..b6e53e50b7a5 --- /dev/null +++ b/iop/sound/sdhd/include/sdhd.h @@ -0,0 +1,425 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifndef _SDHD_H +#define _SDHD_H + +#ifdef _IOP +#include +#endif + +typedef struct sceHardSynthSplitBlock_ +{ + u16 sampleSetIndex; + u8 splitRangeLow; + u8 splitCrossFade; + u8 splitRangeHigh; + u8 splitNumber; + u16 splitBendRangeLow; + u16 splitBendRangeHigh; + char keyFollowPitch; + u8 keyFollowPitchCenter; + char keyFollowAmp; + u8 keyFollowAmpCenter; + char keyFollowPan; + u8 keyFollowPanCenter; + u8 splitVolume; + char splitPanpot; + char splitTranspose; + char splitDetune; +} sceHardSynthSplitBlock; + +typedef struct sceHardSynthProgramParam_ +{ + unsigned int splitBlockAddr; + u8 nSplit; + u8 sizeSplitBlock; + u8 progVolume; + char progPanpot; + char progTranspose; + char progDetune; + char keyFollowPan; + u8 keyFollowPanCenter; + u8 progAttr; + u8 dmy; + u8 progLfoWave; + u8 progLfoWave2; + u8 progLfoStartPhase; + u8 progLfoStartPhase2; + u8 progLfoPhaseRandom; + u8 progLfoPhaseRandom2; + u16 progLfoFreq; + u16 progLfoFreq2; + s16 progLfoPitchDepth; + s16 progLfoPitchDepth2; + s16 progLfoMidiPitchDepth; + s16 progLfoMidiPitchDepth2; + char progLfoAmpDepth; + char progLfoAmpDepth2; + char progLfoMidiAmpDepth; + char progLfoMidiAmpDepth2; + sceHardSynthSplitBlock splitBlock[]; +} sceHardSynthProgramParam; + +struct SceSdHdProgramCommon_ +{ + unsigned int volume; + int panpot; + int transpose; + int detune; +}; + +typedef struct SceSdHdProgramCommon_ SceSdHdProgramCommon; +typedef struct SceSdHdProgramCommon_ SceSdHdSplitCommon; + +typedef struct SceSdHdProgramKeyFollow_ +{ + int pan; + unsigned int panCenter; +} SceSdHdProgramKeyFollow; + +typedef struct SceSdHdProgramLFO_ +{ + unsigned int wavePitch; + unsigned int waveAmp; + unsigned int startPhasePitch; + unsigned int startPhaseAmp; + unsigned int phaseRandomPitch; + unsigned int phaseRandomAmp; + unsigned int cyclePitch; + unsigned int cycleAmp; + int pitchDepthUp; + int pitchDepthDown; + int midiPitchDepthUp; + int midiPitchDepthDown; + int ampDepthUp; + int ampDepthDown; + int midiAmpDepthUp; + int midiAmpDepthDown; +} SceSdHdProgramLFO; + +typedef struct SceSdHdProgramParam_ +{ + unsigned int nSplit; + unsigned int progAttr; + SceSdHdProgramCommon common; + SceSdHdProgramKeyFollow keyFollow; + SceSdHdProgramLFO LFO; +} SceSdHdProgramParam; + +struct SceSdHdSplitRange_ +{ + unsigned int low; + unsigned int crossFade; + unsigned int high; +}; + +typedef struct SceSdHdSplitRange_ SceSdHdSplitRange; +typedef struct SceSdHdSplitRange_ SceSdHdSampleVelRange; + +typedef struct SceSdHdSplitBendRange_ +{ + unsigned int low; + unsigned int high; +} SceSdHdSplitBendRange; + +typedef struct SceSdHdSplitKeyFollow_ +{ + int pitch; + unsigned int pitchCenter; + int amp; + unsigned int ampCenter; + int pan; + unsigned int panCenter; +} SceSdHdSplitKeyFollow; + +typedef struct SceSdHdSplitBlock_ +{ + unsigned int sampleSetIndex; + unsigned int splitNumber; + SceSdHdSplitRange range; + SceSdHdSplitBendRange bendRange; + SceSdHdSplitKeyFollow keyFollow; + SceSdHdSplitCommon common; +} SceSdHdSplitBlock; + +typedef struct sceHardSynthSampleSetParam_ +{ + u8 velCurve; + u8 velLimitLow; + u8 velLimitHigh; + u8 nSample; + u16 sampleIndex[]; +} sceHardSynthSampleSetParam; + +typedef struct SceSdHdSampleSetParam_ +{ + unsigned int velCurve; + unsigned int velLimitLow; + unsigned int velLimitHigh; + unsigned int nSample; +} SceSdHdSampleSetParam; + +typedef struct sceHardSynthSampleParam_ +{ + u16 VagIndex; + u8 velRangeLow; + u8 velCrossFade; + u8 velRangeHigh; + char velFollowPitch; + u8 velFollowPitchCenter; + u8 velFollowPitchVelCurve; + char velFollowAmp; + u8 velFollowAmpCenter; + u8 velFollowAmpVelCurve; + u8 sampleBaseNote; + char sampleDetune; + char samplePanpot; + u8 sampleGroup; + u8 samplePriority; + u8 sampleVolume; + u8 dmy; + u16 sampleAdsr1; + u16 sampleAdsr2; + char keyFollowAr; + u8 keyFollowArCenter; + char keyFollowDr; + u8 keyFollowDrCenter; + char keyFollowSr; + u8 keyFollowSrCenter; + char keyFollowRr; + u8 keyFollowRrCenter; + char keyFollowSl; + u8 keyFollowSlCenter; + u16 samplePitchLfoDelay; + u16 samplePitchLfoFade; + u16 sampleAmpLfoDelay; + u16 sampleAmpLfoFade; + u8 sampleLfoAttr; + u8 sampleSpuAttr; +} sceHardSynthSampleParam; + +typedef struct SceSdHdSampleVelFollow_ +{ + int pitch; + unsigned int pitchCenter; + unsigned int pitchVelCurve; + int amp; + unsigned int ampCenter; + unsigned int ampVelCurve; +} SceSdHdSampleVelFollow; + +typedef struct SceSdHdSampleCommon_ +{ + unsigned int baseNote; + int detune; + int panpot; + unsigned int group; + unsigned int priority; + unsigned int volume; +} SceSdHdSampleCommon; + +typedef struct SceSdHdSampleADSR_ +{ + unsigned int ADSR1; + unsigned int ADSR2; +} SceSdHdSampleADSR; + +typedef struct SceSdHdSampleKeyFollow_ +{ + int ar; + unsigned int arCenter; + int dr; + unsigned int drCenter; + int sr; + unsigned int srCenter; + int rr; + unsigned int rrCenter; + int sl; + unsigned int slCenter; +} SceSdHdSampleKeyFollow; + +typedef struct SceSdHdSampleLFO_ +{ + unsigned int pitchLFODelay; + unsigned int pitchLFOFade; + unsigned int ampLFODelay; + unsigned int ampLFOFade; +} SceSdHdSampleLFO; + +typedef struct SceSdHdSampleParam_ +{ + int vagIndex; + unsigned int spuAttr; + unsigned int lfoAttr; + SceSdHdSampleVelRange velRange; + SceSdHdSampleVelFollow velFollow; + SceSdHdSampleCommon common; + SceSdHdSampleADSR ADSR; + SceSdHdSampleKeyFollow keyFollow; + SceSdHdSampleLFO LFO; +} SceSdHdSampleParam; + +typedef struct sceHardSynthVagParam_ +{ + unsigned int vagOffsetAddr; + u16 vagSampleRate; + u8 vagAttribute; + u8 dmy; +} sceHardSynthVagParam; + +typedef struct SceSdHdVAGInfoParam_ +{ + unsigned int vagOffsetAddr; + unsigned int vagSize; + unsigned int vagSampleRate; + unsigned int vagAttribute; +} SceSdHdVAGInfoParam; + +extern int sceSdHdGetMaxProgramNumber(void *buffer); +extern int sceSdHdGetMaxSampleSetNumber(void *buffer); +extern int sceSdHdGetMaxSampleNumber(void *buffer); +extern int sceSdHdGetMaxVAGInfoNumber(void *buffer); +extern int sceSdHdGetProgramParamAddr(void *buffer, unsigned int programNumber, sceHardSynthProgramParam **ptr); +extern int sceSdHdGetProgramParam(void *buffer, unsigned int programNumber, SceSdHdProgramParam *param); +extern int sceSdHdGetSplitBlockAddr( + void *buffer, unsigned int programNumber, unsigned int splitBlockNumber, sceHardSynthSplitBlock **theParamPtr); +extern int +sceSdHdGetSplitBlock(void *buffer, unsigned int programNumber, unsigned int splitBlockNumber, SceSdHdSplitBlock *param); +extern int sceSdHdGetSampleSetParamAddr(void *buffer, unsigned int sampleSetNumber, sceHardSynthSampleSetParam **ptr); +extern int sceSdHdGetSampleSetParam(void *buffer, unsigned int sampleSetNumber, SceSdHdSampleSetParam *param); +extern int sceSdHdGetSampleParamAddr(void *buffer, unsigned int sampleNumber, sceHardSynthSampleParam **ptr); +extern int sceSdHdGetSampleParam(void *buffer, unsigned int sampleNumber, SceSdHdSampleParam *param); +extern int sceSdHdGetVAGInfoParamAddr(void *buffer, unsigned int vagInfoNumber, sceHardSynthVagParam **ptr); +extern int sceSdHdGetVAGInfoParam(void *buffer, unsigned int vagInfoNumber, SceSdHdVAGInfoParam *param); +extern int sceSdHdCheckProgramNumber(void *buffer, unsigned int programNumber); +extern int sceSdHdGetSplitBlockCountByNote(void *buffer, unsigned int programNumber, unsigned int noteNumber); +extern int sceSdHdGetSplitBlockAddrByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, sceHardSynthSplitBlock **ptr); +extern int +sceSdHdGetSplitBlockByNote(void *buffer, unsigned int programNumber, unsigned int noteNumber, SceSdHdSplitBlock *param); +extern int sceSdHdGetSampleSetParamCountByNote(void *buffer, unsigned int programNumber, unsigned int noteNumber); +extern int sceSdHdGetSampleSetParamAddrByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, sceHardSynthSampleSetParam **ptr); +extern int sceSdHdGetSampleSetParamByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, SceSdHdSampleSetParam *param); +extern int sceSdHdGetSampleParamCountByNoteVelocity( + void *buffer, unsigned int programNumber, unsigned int noteNumber, unsigned int velocity, unsigned int mode); +extern int sceSdHdGetSampleParamAddrByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + sceHardSynthSampleParam **ptr); +extern int sceSdHdGetSampleParamByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + SceSdHdSampleParam *param); +extern int sceSdHdGetVAGInfoParamCountByNoteVelocity( + void *buffer, unsigned int programNumber, unsigned int noteNumber, unsigned int velocity, unsigned int mode); +extern int sceSdHdGetVAGInfoParamAddrByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + sceHardSynthVagParam **ptr); +extern int sceSdHdGetVAGInfoParamByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + SceSdHdVAGInfoParam *param); +extern int sceSdHdGetSampleParamCountByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode); +extern int sceSdHdGetSampleParamAddrByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, sceHardSynthSampleParam **ptr); +extern int sceSdHdGetSampleParamByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, SceSdHdSampleParam *param); +extern int sceSdHdGetVAGInfoParamCountByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode); +extern int sceSdHdGetVAGInfoParamAddrByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, sceHardSynthVagParam **ptr); +extern int sceSdHdGetVAGInfoParamByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, SceSdHdVAGInfoParam *param); +extern int +sceSdHdGetVAGInfoParamAddrBySampleNumber(void *buffer, unsigned int sampleNumber, sceHardSynthVagParam **ptr); +extern int sceSdHdGetVAGInfoParamBySampleNumber(void *buffer, unsigned int sampleNumber, SceSdHdVAGInfoParam *param); +extern int sceSdHdGetSplitBlockNumberBySplitNumber(void *buffer, unsigned int programNumber, unsigned int splitNumber); +extern int sceSdHdGetVAGSize(void *buffer, unsigned int vagInfoNumber); +extern int sceSdHdGetSplitBlockCount(void *buffer, unsigned int programNumber); +extern int sceSdHdGetMaxSplitBlockCount(void *buffer); +extern int sceSdHdGetMaxSampleSetParamCount(void *buffer); +extern int sceSdHdGetMaxSampleParamCount(void *buffer); +extern int sceSdHdGetMaxVAGInfoParamCount(void *buffer); +extern int sceSdHdModifyVelocity(unsigned int curveType, int velocity); +extern int sceSdHdModifyVelocityLFO(unsigned int curveType, int velocity, int center); +extern int sceSdHdGetValidProgramNumberCount(void *buffer); +extern int sceSdHdGetValidProgramNumber(void *buffer, unsigned int *ptr); +extern int +sceSdHdGetSampleNumberBySampleIndex(void *buffer, unsigned int sampleSetNumber, unsigned int sampleIndexNumber); + +#define sdhd_IMPORTS_start DECLARE_IMPORT_TABLE(sdhd, 1, 2) +#define sdhd_IMPORTS_end END_IMPORT_TABLE + +#define I_sceSdHdGetMaxProgramNumber DECLARE_IMPORT(4, sceSdHdGetMaxProgramNumber) +#define I_sceSdHdGetMaxSampleSetNumber DECLARE_IMPORT(5, sceSdHdGetMaxSampleSetNumber) +#define I_sceSdHdGetMaxSampleNumber DECLARE_IMPORT(6, sceSdHdGetMaxSampleNumber) +#define I_sceSdHdGetMaxVAGInfoNumber DECLARE_IMPORT(7, sceSdHdGetMaxVAGInfoNumber) +#define I_sceSdHdGetProgramParamAddr DECLARE_IMPORT(8, sceSdHdGetProgramParamAddr) +#define I_sceSdHdGetProgramParam DECLARE_IMPORT(9, sceSdHdGetProgramParam) +#define I_sceSdHdGetSplitBlockAddr DECLARE_IMPORT(10, sceSdHdGetSplitBlockAddr) +#define I_sceSdHdGetSplitBlock DECLARE_IMPORT(11, sceSdHdGetSplitBlock) +#define I_sceSdHdGetSampleSetParamAddr DECLARE_IMPORT(12, sceSdHdGetSampleSetParamAddr) +#define I_sceSdHdGetSampleSetParam DECLARE_IMPORT(13, sceSdHdGetSampleSetParam) +#define I_sceSdHdGetSampleParamAddr DECLARE_IMPORT(14, sceSdHdGetSampleParamAddr) +#define I_sceSdHdGetSampleParam DECLARE_IMPORT(15, sceSdHdGetSampleParam) +#define I_sceSdHdGetVAGInfoParamAddr DECLARE_IMPORT(16, sceSdHdGetVAGInfoParamAddr) +#define I_sceSdHdGetVAGInfoParam DECLARE_IMPORT(17, sceSdHdGetVAGInfoParam) +#define I_sceSdHdCheckProgramNumber DECLARE_IMPORT(18, sceSdHdCheckProgramNumber) +#define I_sceSdHdGetSplitBlockCountByNote DECLARE_IMPORT(19, sceSdHdGetSplitBlockCountByNote) +#define I_sceSdHdGetSplitBlockAddrByNote DECLARE_IMPORT(20, sceSdHdGetSplitBlockAddrByNote) +#define I_sceSdHdGetSplitBlockByNote DECLARE_IMPORT(21, sceSdHdGetSplitBlockByNote) +#define I_sceSdHdGetSampleSetParamCountByNote DECLARE_IMPORT(22, sceSdHdGetSampleSetParamCountByNote) +#define I_sceSdHdGetSampleSetParamAddrByNote DECLARE_IMPORT(23, sceSdHdGetSampleSetParamAddrByNote) +#define I_sceSdHdGetSampleSetParamByNote DECLARE_IMPORT(24, sceSdHdGetSampleSetParamByNote) +#define I_sceSdHdGetSampleParamCountByNoteVelocity DECLARE_IMPORT(25, sceSdHdGetSampleParamCountByNoteVelocity) +#define I_sceSdHdGetSampleParamAddrByNoteVelocity DECLARE_IMPORT(26, sceSdHdGetSampleParamAddrByNoteVelocity) +#define I_sceSdHdGetSampleParamByNoteVelocity DECLARE_IMPORT(27, sceSdHdGetSampleParamByNoteVelocity) +#define I_sceSdHdGetVAGInfoParamCountByNoteVelocity DECLARE_IMPORT(28, sceSdHdGetVAGInfoParamCountByNoteVelocity) +#define I_sceSdHdGetVAGInfoParamAddrByNoteVelocity DECLARE_IMPORT(29, sceSdHdGetVAGInfoParamAddrByNoteVelocity) +#define I_sceSdHdGetVAGInfoParamByNoteVelocity DECLARE_IMPORT(30, sceSdHdGetVAGInfoParamByNoteVelocity) +#define I_sceSdHdGetSampleParamCountByVelocity DECLARE_IMPORT(31, sceSdHdGetSampleParamCountByVelocity) +#define I_sceSdHdGetSampleParamAddrByVelocity DECLARE_IMPORT(32, sceSdHdGetSampleParamAddrByVelocity) +#define I_sceSdHdGetSampleParamByVelocity DECLARE_IMPORT(33, sceSdHdGetSampleParamByVelocity) +#define I_sceSdHdGetVAGInfoParamCountByVelocity DECLARE_IMPORT(34, sceSdHdGetVAGInfoParamCountByVelocity) +#define I_sceSdHdGetVAGInfoParamAddrByVelocity DECLARE_IMPORT(35, sceSdHdGetVAGInfoParamAddrByVelocity) +#define I_sceSdHdGetVAGInfoParamByVelocity DECLARE_IMPORT(36, sceSdHdGetVAGInfoParamByVelocity) +#define I_sceSdHdGetVAGInfoParamAddrBySampleNumber DECLARE_IMPORT(37, sceSdHdGetVAGInfoParamAddrBySampleNumber) +#define I_sceSdHdGetVAGInfoParamBySampleNumber DECLARE_IMPORT(38, sceSdHdGetVAGInfoParamBySampleNumber) +#define I_sceSdHdGetSplitBlockNumberBySplitNumber DECLARE_IMPORT(39, sceSdHdGetSplitBlockNumberBySplitNumber) +#define I_sceSdHdGetVAGSize DECLARE_IMPORT(40, sceSdHdGetVAGSize) +#define I_sceSdHdGetSplitBlockCount DECLARE_IMPORT(41, sceSdHdGetSplitBlockCount) +#define I_sceSdHdGetMaxSplitBlockCount DECLARE_IMPORT(42, sceSdHdGetMaxSplitBlockCount) +#define I_sceSdHdGetMaxSampleSetParamCount DECLARE_IMPORT(43, sceSdHdGetMaxSampleSetParamCount) +#define I_sceSdHdGetMaxSampleParamCount DECLARE_IMPORT(44, sceSdHdGetMaxSampleParamCount) +#define I_sceSdHdGetMaxVAGInfoParamCount DECLARE_IMPORT(45, sceSdHdGetMaxVAGInfoParamCount) +#define I_sceSdHdModifyVelocity DECLARE_IMPORT(46, sceSdHdModifyVelocity) +#define I_sceSdHdModifyVelocityLFO DECLARE_IMPORT(47, sceSdHdModifyVelocityLFO) +#define I_sceSdHdGetValidProgramNumberCount DECLARE_IMPORT(48, sceSdHdGetValidProgramNumberCount) +#define I_sceSdHdGetValidProgramNumber DECLARE_IMPORT(49, sceSdHdGetValidProgramNumber) +#define I_sceSdHdGetSampleNumberBySampleIndex DECLARE_IMPORT(50, sceSdHdGetSampleNumberBySampleIndex) + +#endif diff --git a/iop/sound/sdhd/src/exports.tab b/iop/sound/sdhd/src/exports.tab new file mode 100644 index 000000000000..02d5cf37be89 --- /dev/null +++ b/iop/sound/sdhd/src/exports.tab @@ -0,0 +1,56 @@ + +DECLARE_EXPORT_TABLE(sdhd, 1, 2) + DECLARE_EXPORT(_start) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(sceSdHdGetMaxProgramNumber) + DECLARE_EXPORT(sceSdHdGetMaxSampleSetNumber) + DECLARE_EXPORT(sceSdHdGetMaxSampleNumber) + DECLARE_EXPORT(sceSdHdGetMaxVAGInfoNumber) + DECLARE_EXPORT(sceSdHdGetProgramParamAddr) + DECLARE_EXPORT(sceSdHdGetProgramParam) + DECLARE_EXPORT(sceSdHdGetSplitBlockAddr) + DECLARE_EXPORT(sceSdHdGetSplitBlock) + DECLARE_EXPORT(sceSdHdGetSampleSetParamAddr) + DECLARE_EXPORT(sceSdHdGetSampleSetParam) + DECLARE_EXPORT(sceSdHdGetSampleParamAddr) + DECLARE_EXPORT(sceSdHdGetSampleParam) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamAddr) + DECLARE_EXPORT(sceSdHdGetVAGInfoParam) + DECLARE_EXPORT(sceSdHdCheckProgramNumber) + DECLARE_EXPORT(sceSdHdGetSplitBlockCountByNote) + DECLARE_EXPORT(sceSdHdGetSplitBlockAddrByNote) + DECLARE_EXPORT(sceSdHdGetSplitBlockByNote) + DECLARE_EXPORT(sceSdHdGetSampleSetParamCountByNote) + DECLARE_EXPORT(sceSdHdGetSampleSetParamAddrByNote) + DECLARE_EXPORT(sceSdHdGetSampleSetParamByNote) + DECLARE_EXPORT(sceSdHdGetSampleParamCountByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetSampleParamAddrByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetSampleParamByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamCountByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamAddrByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamByNoteVelocity) + DECLARE_EXPORT(sceSdHdGetSampleParamCountByVelocity) + DECLARE_EXPORT(sceSdHdGetSampleParamAddrByVelocity) + DECLARE_EXPORT(sceSdHdGetSampleParamByVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamCountByVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamAddrByVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamByVelocity) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamAddrBySampleNumber) + DECLARE_EXPORT(sceSdHdGetVAGInfoParamBySampleNumber) + DECLARE_EXPORT(sceSdHdGetSplitBlockNumberBySplitNumber) + DECLARE_EXPORT(sceSdHdGetVAGSize) + DECLARE_EXPORT(sceSdHdGetSplitBlockCount) + DECLARE_EXPORT(sceSdHdGetMaxSplitBlockCount) + DECLARE_EXPORT(sceSdHdGetMaxSampleSetParamCount) + DECLARE_EXPORT(sceSdHdGetMaxSampleParamCount) + DECLARE_EXPORT(sceSdHdGetMaxVAGInfoParamCount) + DECLARE_EXPORT(sceSdHdModifyVelocity) + DECLARE_EXPORT(sceSdHdModifyVelocityLFO) + DECLARE_EXPORT(sceSdHdGetValidProgramNumberCount) + DECLARE_EXPORT(sceSdHdGetValidProgramNumber) + DECLARE_EXPORT(sceSdHdGetSampleNumberBySampleIndex) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/sound/sdhd/src/imports.lst b/iop/sound/sdhd/src/imports.lst new file mode 100644 index 000000000000..2e04806b24bf --- /dev/null +++ b/iop/sound/sdhd/src/imports.lst @@ -0,0 +1,10 @@ + +intrman_IMPORTS_start +I_CpuSuspendIntr +I_CpuResumeIntr +intrman_IMPORTS_end + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_ReleaseLibraryEntries +loadcore_IMPORTS_end diff --git a/iop/sound/sdhd/src/irx_imports.h b/iop/sound/sdhd/src/irx_imports.h new file mode 100644 index 000000000000..d5c0fba6bda2 --- /dev/null +++ b/iop/sound/sdhd/src/irx_imports.h @@ -0,0 +1,23 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ + +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/sound/sdhd/src/sdhd.c b/iop/sound/sdhd/src/sdhd.c new file mode 100644 index 000000000000..fddabc2c6d86 --- /dev/null +++ b/iop/sound/sdhd/src/sdhd.c @@ -0,0 +1,1534 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifdef _IOP +#include "irx_imports.h" +#else +#include +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#endif +#include + +#ifdef _IOP +IRX_ID("Sound_Data_HD", 2, 2); +#endif +// Based on the module from SCE SDK 3.1.0. + +struct sceHardSynthVersionChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + u16 reserved; + u8 versionMajor; + u8 versionMinor; +}; + +typedef struct sceHardSynthVersionChunk_ sceHardSynthVersionChunk; +typedef struct sceHardSynthVersionChunk_ sceSeqVersionChunk; + +typedef struct sceHardSynthHeaderChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int headerSize; + unsigned int bodySize; + unsigned int programChunkAddr; + unsigned int sampleSetChunkAddr; + unsigned int sampleChunkAddr; + unsigned int vagInfoChunkAddr; + unsigned int seTimbreChunkAddr; +} sceHardSynthHeaderChunk; + +typedef struct sceHardSynthProgramChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxProgramNumber; + unsigned int programOffsetAddr[]; +} sceHardSynthProgramChunk; + +typedef struct sceHardSynthSampleSetChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxSampleSetNumber; + unsigned int sampleSetOffsetAddr[]; +} sceHardSynthSampleSetChunk; + +typedef struct sceHardSynthSampleChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxSampleNumber; + unsigned int sampleOffsetAddr[]; +} sceHardSynthSampleChunk; + +typedef struct sceHardSynthVagInfoChunk +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxVagInfoNumber; + unsigned int vagInfoOffsetAddr[]; +} sceHardSynthVagInfoChunk; + +struct sdhd_info +{ + sceHardSynthVersionChunk *m_vers; + sceHardSynthHeaderChunk *m_head; + sceHardSynthProgramChunk *m_prog; + sceHardSynthSampleSetChunk *m_sset; + sceHardSynthSampleChunk *m_smpl; + sceHardSynthVagInfoChunk *m_vagi; +}; + +#ifdef _IOP +extern struct irx_export_table _exp_sdhd; +#endif + +static unsigned int do_get_vers_head_chunk(sceHardSynthVersionChunk *indata, struct sdhd_info *dinfo) +{ + dinfo->m_vers = 0; + dinfo->m_head = 0; + dinfo->m_prog = 0; + dinfo->m_sset = 0; + dinfo->m_smpl = 0; + dinfo->m_vagi = 0; + dinfo->m_vers = indata; + if ( indata->Creator != 0x53434549 || indata->Type != 0x56657273 ) + { + dinfo->m_vers = 0; + return 0x8103000E; + } + if ( (indata->chunkSize & 0x80000000) ) + { + dinfo->m_vers = 0; + return 0x8103002F; + } + dinfo->m_head = (sceHardSynthHeaderChunk *)((char *)indata + indata->chunkSize); + if ( dinfo->m_head->Creator != 0x53434549 || dinfo->m_head->Type != 0x48656164 ) + { + dinfo->m_vers = 0; + dinfo->m_head = 0; + return 0x8103002F; + } + return 0; +} + +static unsigned int do_get_prog_chunk(void *indata, struct sdhd_info *dinfo) +{ + if ( dinfo->m_head->programChunkAddr == 0xFFFFFFFF ) + return 0x81039005; + if ( (dinfo->m_head->programChunkAddr & 0x80000000) ) + return 0x8103002F; + dinfo->m_prog = (sceHardSynthProgramChunk *)((char *)indata + dinfo->m_head->programChunkAddr); + if ( dinfo->m_prog->Creator != 0x53434549 || dinfo->m_prog->Type != 0x50726F67 ) + { + dinfo->m_prog = 0; + return 0x8103002F; + } + return 0; +} + +static unsigned int do_get_sset_chunk(void *indata, struct sdhd_info *dinfo) +{ + if ( dinfo->m_head->sampleSetChunkAddr == 0xFFFFFFFF ) + return 0x81039006; + if ( (dinfo->m_head->sampleSetChunkAddr & 0x80000000) ) + return 0x8103002F; + dinfo->m_sset = (sceHardSynthSampleSetChunk *)((char *)indata + dinfo->m_head->sampleSetChunkAddr); + if ( dinfo->m_sset->Creator != 0x53434549 || dinfo->m_sset->Type != 0x53736574 ) + { + dinfo->m_sset = 0; + return 0x8103002F; + } + return 0; +} + +static unsigned int do_get_smpl_chunk(void *indata, struct sdhd_info *dinfo) +{ + if ( dinfo->m_head->sampleChunkAddr == 0xFFFFFFFF ) + return 0x81039007; + if ( (dinfo->m_head->sampleChunkAddr & 0x80000000) ) + return 0x8103002F; + dinfo->m_smpl = (sceHardSynthSampleChunk *)((char *)indata + dinfo->m_head->sampleChunkAddr); + if ( dinfo->m_smpl->Creator != 0x53434549 || dinfo->m_smpl->Type != 0x536D706C ) + { + dinfo->m_smpl = 0; + return 0x8103002F; + } + return 0; +} + +static unsigned int do_get_vagi_chunk(void *indata, struct sdhd_info *dinfo) +{ + if ( dinfo->m_head->vagInfoChunkAddr == 0xFFFFFFFF ) + return 0x81039008; + if ( (dinfo->m_head->vagInfoChunkAddr & 0x80000000) ) + return 0x8103002F; + dinfo->m_vagi = (sceHardSynthVagInfoChunk *)((char *)indata + dinfo->m_head->vagInfoChunkAddr); + if ( dinfo->m_vagi->Creator != 0x53434549 || dinfo->m_vagi->Type != 0x56616769 ) + { + dinfo->m_vagi = 0; + return 0x8103002F; + } + return 0; +} + +static void do_copy_to_sdhd_program_param(SceSdHdProgramParam *dst, const sceHardSynthProgramParam *src) +{ + dst->nSplit = src->nSplit; + dst->progAttr = src->progAttr; + dst->common.volume = src->progVolume; + dst->common.panpot = src->progPanpot; + dst->common.transpose = src->progTranspose; + dst->common.detune = src->progDetune; + dst->keyFollow.pan = src->keyFollowPan; + dst->keyFollow.panCenter = src->keyFollowPanCenter; + dst->LFO.wavePitch = src->progLfoWave; + dst->LFO.waveAmp = src->progLfoWave2; + dst->LFO.startPhasePitch = src->progLfoStartPhase; + dst->LFO.startPhaseAmp = src->progLfoStartPhase2; + dst->LFO.phaseRandomPitch = src->progLfoPhaseRandom; + dst->LFO.phaseRandomAmp = src->progLfoPhaseRandom2; + dst->LFO.cyclePitch = src->progLfoFreq; + dst->LFO.cycleAmp = src->progLfoFreq2; + dst->LFO.pitchDepthUp = src->progLfoPitchDepth; + dst->LFO.pitchDepthDown = src->progLfoPitchDepth2; + dst->LFO.midiPitchDepthUp = src->progLfoMidiPitchDepth; + dst->LFO.midiPitchDepthDown = src->progLfoMidiPitchDepth2; + dst->LFO.ampDepthUp = src->progLfoAmpDepth; + dst->LFO.ampDepthDown = src->progLfoAmpDepth2; + dst->LFO.midiAmpDepthUp = src->progLfoMidiAmpDepth; + dst->LFO.midiAmpDepthDown = src->progLfoMidiAmpDepth2; +} + +static void do_copy_to_sdhd_split_block(SceSdHdSplitBlock *dst, const sceHardSynthSplitBlock *src) +{ + dst->sampleSetIndex = src->sampleSetIndex; + dst->splitNumber = src->splitNumber; + dst->range.low = src->splitRangeLow; + dst->range.crossFade = src->splitCrossFade; + dst->range.high = src->splitRangeHigh; + dst->bendRange.low = src->splitBendRangeLow; + dst->bendRange.high = src->splitBendRangeHigh; + dst->keyFollow.pitch = src->keyFollowPitch; + dst->keyFollow.pitchCenter = src->keyFollowPitchCenter; + dst->keyFollow.amp = src->keyFollowAmp; + dst->keyFollow.ampCenter = src->keyFollowAmpCenter; + dst->keyFollow.pan = src->keyFollowPan; + dst->keyFollow.panCenter = src->keyFollowPanCenter; + dst->common.volume = src->splitVolume; + dst->common.panpot = src->splitPanpot; + dst->common.transpose = src->splitTranspose; + dst->common.detune = src->splitDetune; +} + +static void do_copy_to_sdhd_set_param(SceSdHdSampleSetParam *dst, const sceHardSynthSampleSetParam *src) +{ + dst->velCurve = src->velCurve; + dst->velLimitLow = src->velLimitLow; + dst->velLimitHigh = src->velLimitHigh; + dst->nSample = src->nSample; +} + +static void do_copy_to_sdhd_sample_param(SceSdHdSampleParam *dst, const sceHardSynthSampleParam *src) +{ + dst->vagIndex = src->VagIndex; + dst->spuAttr = src->sampleSpuAttr; + dst->lfoAttr = src->sampleLfoAttr; + dst->velRange.low = src->velRangeLow; + dst->velRange.crossFade = src->velCrossFade; + dst->velRange.high = src->velRangeHigh; + dst->velFollow.pitch = src->velFollowPitch; + dst->velFollow.pitchCenter = src->velFollowPitchCenter; + dst->velFollow.pitchVelCurve = src->velFollowPitchVelCurve; + dst->velFollow.amp = src->velFollowAmp; + dst->velFollow.ampCenter = src->velFollowAmpCenter; + dst->velFollow.ampVelCurve = src->velFollowAmpVelCurve; + dst->common.baseNote = src->sampleBaseNote; + dst->common.detune = src->sampleDetune; + dst->common.panpot = src->samplePanpot; + dst->common.group = src->sampleGroup; + dst->common.priority = src->samplePriority; + dst->common.volume = src->sampleVolume; + dst->ADSR.ADSR1 = src->sampleAdsr1; + dst->ADSR.ADSR2 = src->sampleAdsr2; + dst->keyFollow.ar = src->keyFollowAr; + dst->keyFollow.arCenter = src->keyFollowArCenter; + dst->keyFollow.dr = src->keyFollowDr; + dst->keyFollow.drCenter = src->keyFollowDrCenter; + dst->keyFollow.sr = src->keyFollowSr; + dst->keyFollow.srCenter = src->keyFollowSrCenter; + dst->keyFollow.rr = src->keyFollowRr; + dst->keyFollow.rrCenter = src->keyFollowRrCenter; + dst->keyFollow.sl = src->keyFollowSl; + dst->keyFollow.slCenter = src->keyFollowSlCenter; + dst->LFO.pitchLFODelay = src->samplePitchLfoDelay; + dst->LFO.pitchLFOFade = src->samplePitchLfoFade; + dst->LFO.ampLFODelay = src->sampleAmpLfoDelay; + dst->LFO.ampLFOFade = src->sampleAmpLfoFade; +} + +static void do_copy_to_sdhd_vag_info_param(SceSdHdVAGInfoParam *dst, unsigned int sz, const sceHardSynthVagParam *src) +{ + dst->vagOffsetAddr = src->vagOffsetAddr; + dst->vagSampleRate = src->vagSampleRate; + dst->vagSize = sz; + dst->vagAttribute = src->vagAttribute; +} + +static unsigned int do_get_vag_size(sceHardSynthVersionChunk *indata, const unsigned int *vagoffsaddr) +{ + unsigned int i; + unsigned int bodySize; + const sceHardSynthVagParam *vagparam; + struct sdhd_info dinfo; + + if ( do_get_vers_head_chunk(indata, &dinfo) || do_get_vagi_chunk(indata, &dinfo) ) + return 0; + bodySize = dinfo.m_head->bodySize; + for ( i = 0; dinfo.m_vagi->maxVagInfoNumber >= i; i += 1 ) + { + if ( dinfo.m_vagi->vagInfoOffsetAddr[i] != 0xFFFFFFFF ) + { + vagparam = (sceHardSynthVagParam *)((char *)(dinfo.m_vagi) + dinfo.m_vagi->vagInfoOffsetAddr[i]); + if ( *vagoffsaddr < vagparam->vagOffsetAddr && vagparam->vagOffsetAddr < bodySize ) + bodySize = vagparam->vagOffsetAddr; + } + } + return bodySize - *vagoffsaddr; +} + +static unsigned int +do_check_chunk_in_bounds(void *indata, const struct sdhd_info *dinfo, unsigned int hdrmagic, unsigned int idx) +{ + (void)indata; + + switch ( hdrmagic ) + { + case 0x536D706C: + { + if ( !dinfo->m_smpl ) + return 0x8103002F; + if ( dinfo->m_smpl->maxSampleNumber < idx ) + return 0x81039014; + if ( dinfo->m_smpl->sampleOffsetAddr[idx] == 0xFFFFFFFF ) + return 0x81039015; + break; + } + case 0x53736574: + { + if ( !dinfo->m_sset ) + return 0x8103002F; + if ( dinfo->m_sset->maxSampleSetNumber < idx ) + return 0x81039012; + if ( dinfo->m_sset->sampleSetOffsetAddr[idx] == 0xFFFFFFFF ) + return 0x81039012; + break; + } + case 0x56616769: + { + if ( !dinfo->m_vagi ) + return 0x8103002F; + if ( dinfo->m_vagi->maxVagInfoNumber < idx ) + return 0x81039016; + if ( dinfo->m_vagi->vagInfoOffsetAddr[idx] == 0xFFFFFFFF ) + return 0x81039017; + break; + } + case 0x50726F67: + { + if ( !dinfo->m_prog ) + return 0x8103002F; + if ( dinfo->m_prog->maxProgramNumber < idx ) + return 0x81039010; + if ( dinfo->m_prog->programOffsetAddr[idx] == 0xFFFFFFFF ) + return 0x81039011; + break; + } + default: + break; + } + return 0; +} + +static int do_get_common_block_ptr_note( + void *buffer, + unsigned int programNumber, + unsigned int swcase, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + void **ptr) +{ + int idx1; + int i; + sceHardSynthSplitBlock *p_splitblock; + int j; + sceHardSynthProgramParam *p_programparam; + sceHardSynthSampleSetParam *p_samplesetparam; + sceHardSynthSampleParam *p_sampleparam; + sceHardSynthVagParam *p_vagparam; + + idx1 = 0; + if ( + sceSdHdGetProgramParamAddr(buffer, programNumber, &p_programparam) || p_programparam->splitBlockAddr == 0xFFFFFFFF ) + { + return 0; + } + for ( i = 0; i < p_programparam->nSplit; i += 1 ) + { + p_splitblock = (sceHardSynthSplitBlock *)((char *)p_programparam + p_programparam->splitBlockAddr + + p_programparam->sizeSplitBlock * i); + if ( noteNumber < (p_splitblock->splitRangeLow & 0x7Fu) || noteNumber > (p_splitblock->splitRangeHigh & 0x7Fu) ) + { + continue; + } + switch ( swcase ) + { + case 0: + idx1 += 1; + break; + case 1: + idx1 += 1; + *ptr = p_splitblock; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 2: + idx1 += 1; + do_copy_to_sdhd_split_block((SceSdHdSplitBlock *)ptr, p_splitblock); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdSplitBlock)); + break; + default: + if ( + p_splitblock->sampleSetIndex == 0xFFFF + || sceSdHdGetSampleSetParamAddr(buffer, p_splitblock->sampleSetIndex, &p_samplesetparam) ) + { + break; + } + switch ( swcase ) + { + case 3: + idx1 += 1; + break; + case 4: + idx1 += 1; + *ptr = p_samplesetparam; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 5: + idx1 += 1; + do_copy_to_sdhd_set_param((SceSdHdSampleSetParam *)ptr, p_samplesetparam); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdSampleSetParam)); + break; + default: + switch ( mode ) + { + case 0: + if ( velocity < p_samplesetparam->velLimitLow || velocity > p_samplesetparam->velLimitHigh ) + { + break; + } + for ( j = 0; j < p_samplesetparam->nSample; j += 1 ) + { + if ( + p_samplesetparam->sampleIndex[j] != 0xFFFF + && !sceSdHdGetSampleParamAddr(buffer, p_samplesetparam->sampleIndex[j], &p_sampleparam) + && velocity >= (p_sampleparam->velRangeLow & 0x7Fu) + && (p_sampleparam->velRangeHigh & 0x7Fu) >= velocity ) + { + switch ( swcase ) + { + case 6: + idx1 += 1; + break; + case 7: + idx1 += 1; + *ptr = p_sampleparam; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 8: + idx1 += 1; + do_copy_to_sdhd_sample_param((SceSdHdSampleParam *)ptr, p_sampleparam); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdSampleParam)); + break; + default: + if ( + p_sampleparam->VagIndex == 0xFFFF + || sceSdHdGetVAGInfoParamAddr(buffer, p_sampleparam->VagIndex, &p_vagparam) ) + { + break; + } + switch ( swcase ) + { + case 9: + idx1 += 1; + break; + case 10: + idx1 += 1; + *ptr = p_vagparam; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 11: + idx1 += 1; + do_copy_to_sdhd_vag_info_param( + (SceSdHdVAGInfoParam *)ptr, + do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), + p_vagparam); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdVAGInfoParam)); + break; + default: + break; + } + break; + } + } + } + break; + case 1: + for ( j = 0; j < p_samplesetparam->nSample; j += 1 ) + { + if ( + p_samplesetparam->sampleIndex[j] != 0xFFFF + && !sceSdHdGetSampleParamAddr(buffer, p_samplesetparam->sampleIndex[j], &p_sampleparam) + && velocity >= (p_sampleparam->velRangeLow & 0x7Fu) + && (p_sampleparam->velRangeHigh & 0x7Fu) >= velocity ) + { + switch ( swcase ) + { + case 6: + idx1 += 1; + break; + case 7: + idx1 += 1; + *ptr = p_sampleparam; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 8: + idx1 += 1; + do_copy_to_sdhd_sample_param((SceSdHdSampleParam *)ptr, p_sampleparam); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdSampleParam)); + break; + default: + if ( + p_sampleparam->VagIndex == 0xFFFF + || sceSdHdGetVAGInfoParamAddr(buffer, p_sampleparam->VagIndex, &p_vagparam) ) + { + break; + } + switch ( swcase ) + { + case 9: + idx1 += 1; + break; + case 10: + idx1 += 1; + *ptr = p_vagparam; + ptr = (void **)(((char *)ptr) + sizeof(void *)); + break; + case 11: + idx1 += 1; + do_copy_to_sdhd_vag_info_param( + (SceSdHdVAGInfoParam *)ptr, + do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), + p_vagparam); + ptr = (void **)(((char *)ptr) + sizeof(SceSdHdVAGInfoParam)); + break; + default: + break; + } + break; + } + } + } + break; + default: + break; + } + break; + } + break; + } + } + return idx1; +} + +static int do_get_common_block_ptr( + void *buffer, + unsigned int sampleSetNumber, + unsigned int swcase, + unsigned int velocity, + unsigned int mode, + void **param) +{ + int idx1; + int i; + sceHardSynthSampleSetParam *p_samplesetparam; + sceHardSynthSampleParam *p_sampleparam; + sceHardSynthVagParam *p_vagparam; + + idx1 = 0; + if ( sceSdHdGetSampleSetParamAddr(buffer, sampleSetNumber, &p_samplesetparam) ) + return 0; + switch ( mode ) + { + case 0: + if ( velocity < p_samplesetparam->velLimitLow || velocity > p_samplesetparam->velLimitHigh ) + return 0; + for ( i = 0; i < p_samplesetparam->nSample; i += 1 ) + { + if ( + p_samplesetparam->sampleIndex[i] != 0xFFFF + && !sceSdHdGetSampleParamAddr(buffer, p_samplesetparam->sampleIndex[i], &p_sampleparam) + && velocity >= (p_sampleparam->velRangeLow & 0x7Fu) && (p_sampleparam->velRangeHigh & 0x7Fu) >= velocity ) + { + switch ( swcase ) + { + case 6: + idx1 += 1; + break; + case 7: + idx1 += 1; + *param = p_sampleparam; + param = (void **)(((char *)param) + sizeof(void *)); + break; + case 8: + idx1 += 1; + do_copy_to_sdhd_sample_param((SceSdHdSampleParam *)param, p_sampleparam); + param = (void **)(((char *)param) + sizeof(SceSdHdSampleParam)); + break; + default: + if ( + p_sampleparam->VagIndex == 0xFFFF + || sceSdHdGetVAGInfoParamAddr(buffer, p_sampleparam->VagIndex, &p_vagparam) ) + { + break; + } + switch ( swcase ) + { + case 9: + idx1 += 1; + break; + case 10: + idx1 += 1; + *param = p_vagparam; + param = (void **)(((char *)param) + sizeof(void *)); + break; + case 11: + idx1 += 1; + do_copy_to_sdhd_vag_info_param( + (SceSdHdVAGInfoParam *)param, + do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), + p_vagparam); + param = (void **)(((char *)param) + sizeof(SceSdHdVAGInfoParam)); + break; + default: + break; + } + } + } + } + return idx1; + case 1: + for ( i = 0; i < p_samplesetparam->nSample; i += 1 ) + { + if ( + p_samplesetparam->sampleIndex[i] != 0xFFFF + && !sceSdHdGetSampleParamAddr(buffer, p_samplesetparam->sampleIndex[i], &p_sampleparam) + && velocity >= (p_sampleparam->velRangeLow & 0x7Fu) && (p_sampleparam->velRangeHigh & 0x7Fu) >= velocity ) + { + switch ( swcase ) + { + case 6: + idx1 += 1; + break; + case 7: + idx1 += 1; + *param = p_sampleparam; + param = (void **)(((char *)param) + sizeof(void *)); + break; + case 8: + idx1 += 1; + do_copy_to_sdhd_sample_param((SceSdHdSampleParam *)param, p_sampleparam); + param = (void **)(((char *)param) + sizeof(SceSdHdSampleParam)); + break; + default: + if ( + p_sampleparam->VagIndex == 0xFFFF + || sceSdHdGetVAGInfoParamAddr(buffer, p_sampleparam->VagIndex, &p_vagparam) ) + break; + switch ( swcase ) + { + case 9: + idx1 += 1; + break; + case 10: + idx1 += 1; + *param = p_vagparam; + param = (void **)(((char *)param) + sizeof(void *)); + break; + case 11: + idx1 += 1; + do_copy_to_sdhd_vag_info_param( + (SceSdHdVAGInfoParam *)param, + do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), + p_vagparam); + param = (void **)(((char *)param) + sizeof(SceSdHdVAGInfoParam)); + break; + default: + break; + } + break; + } + } + } + return idx1; + default: + return 0; + } +} + +int sceSdHdGetMaxProgramNumber(void *buffer) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_prog_chunk(buffer, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_prog->maxProgramNumber; +} + +int sceSdHdGetMaxSampleSetNumber(void *buffer) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_sset_chunk(buffer, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_sset->maxSampleSetNumber; +} + +int sceSdHdGetMaxSampleNumber(void *buffer) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_smpl_chunk(buffer, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_smpl->maxSampleNumber; +} + +int sceSdHdGetMaxVAGInfoNumber(void *buffer) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_vagi_chunk(buffer, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_vagi->maxVagInfoNumber; +} + +int sceSdHdGetProgramParamAddr(void *buffer, unsigned int programNumber, sceHardSynthProgramParam **ptr) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_prog_chunk(buffer, &dinfo); + if ( result ) + return result; + result = (int)do_check_chunk_in_bounds(buffer, &dinfo, 0x50726F67u, programNumber); + if ( result ) + return result; + *ptr = (sceHardSynthProgramParam *)((char *)dinfo.m_prog + dinfo.m_prog->programOffsetAddr[programNumber]); + return 0; +} + +int sceSdHdGetProgramParam(void *buffer, unsigned int programNumber, SceSdHdProgramParam *param) +{ + int result; + sceHardSynthProgramParam *p_programparam; + + result = sceSdHdGetProgramParamAddr(buffer, programNumber, &p_programparam); + if ( result ) + return result; + do_copy_to_sdhd_program_param(param, p_programparam); + return 0; +} + +int sceSdHdGetSplitBlockAddr( + void *buffer, unsigned int programNumber, unsigned int splitBlockNumber, sceHardSynthSplitBlock **theParamPtr) +{ + int result; + sceHardSynthProgramParam *p_programparam; + + result = sceSdHdGetProgramParamAddr(buffer, programNumber, &p_programparam); + if ( result ) + return result; + if ( p_programparam->splitBlockAddr == 0xFFFFFFFF ) + return (int)0x81039009; + if ( (unsigned int)p_programparam->nSplit - 1 < splitBlockNumber ) + return (int)0x81039018; + *theParamPtr = (sceHardSynthSplitBlock *)((char *)p_programparam + p_programparam->splitBlockAddr + + p_programparam->sizeSplitBlock * splitBlockNumber); + return 0; +} + +int sceSdHdGetSplitBlock( + void *buffer, unsigned int programNumber, unsigned int splitBlockNumber, SceSdHdSplitBlock *param) +{ + int result; + sceHardSynthSplitBlock *p_splitblock; + + result = sceSdHdGetSplitBlockAddr(buffer, programNumber, splitBlockNumber, &p_splitblock); + if ( result ) + return result; + do_copy_to_sdhd_split_block(param, p_splitblock); + return 0; +} + +int sceSdHdGetSampleSetParamAddr(void *buffer, unsigned int sampleSetNumber, sceHardSynthSampleSetParam **ptr) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_sset_chunk(buffer, &dinfo); + if ( result ) + return result; + result = (int)do_check_chunk_in_bounds(buffer, &dinfo, 0x53736574, sampleSetNumber); + if ( result ) + return result; + *ptr = (sceHardSynthSampleSetParam *)((char *)dinfo.m_sset + dinfo.m_sset->sampleSetOffsetAddr[sampleSetNumber]); + return 0; +} + +int sceSdHdGetSampleSetParam(void *buffer, unsigned int sampleSetNumber, SceSdHdSampleSetParam *param) +{ + int result; + sceHardSynthSampleSetParam *p_samplesetparam; + + result = sceSdHdGetSampleSetParamAddr(buffer, sampleSetNumber, &p_samplesetparam); + if ( result ) + return result; + do_copy_to_sdhd_set_param(param, p_samplesetparam); + return 0; +} + +int sceSdHdGetSampleParamAddr(void *buffer, unsigned int sampleNumber, sceHardSynthSampleParam **ptr) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_smpl_chunk(buffer, &dinfo); + if ( result ) + return result; + result = (int)do_check_chunk_in_bounds(buffer, &dinfo, 0x536D706C, sampleNumber); + if ( result ) + return result; + *ptr = (sceHardSynthSampleParam *)((char *)dinfo.m_smpl + dinfo.m_smpl->sampleOffsetAddr[sampleNumber]); + return 0; +} + +int sceSdHdGetSampleParam(void *buffer, unsigned int sampleNumber, SceSdHdSampleParam *param) +{ + int result; + sceHardSynthSampleParam *p_sampleparam; + + result = sceSdHdGetSampleParamAddr(buffer, sampleNumber, &p_sampleparam); + if ( result ) + return result; + do_copy_to_sdhd_sample_param(param, p_sampleparam); + return 0; +} + +int sceSdHdGetVAGInfoParamAddr(void *buffer, unsigned int vagInfoNumber, sceHardSynthVagParam **ptr) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_vagi_chunk(buffer, &dinfo); + if ( result ) + return result; + result = (int)do_check_chunk_in_bounds(buffer, &dinfo, 0x56616769, vagInfoNumber); + if ( result ) + return result; + *ptr = (sceHardSynthVagParam *)((char *)dinfo.m_vagi + dinfo.m_vagi->vagInfoOffsetAddr[vagInfoNumber]); + return 0; +} + +int sceSdHdGetVAGInfoParam(void *buffer, unsigned int vagInfoNumber, SceSdHdVAGInfoParam *param) +{ + int result; + sceHardSynthVagParam *p_vagparam; + + result = sceSdHdGetVAGInfoParamAddr(buffer, vagInfoNumber, &p_vagparam); + if ( result ) + return result; + do_copy_to_sdhd_vag_info_param( + param, do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), p_vagparam); + return 0; +} + +int sceSdHdCheckProgramNumber(void *buffer, unsigned int programNumber) +{ + int result; + struct sdhd_info dinfo; + + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_prog_chunk(buffer, &dinfo); + if ( result ) + return result; + return (int)do_check_chunk_in_bounds(buffer, &dinfo, 0x50726F67, programNumber); +} + +int sceSdHdGetSplitBlockCountByNote(void *buffer, unsigned int programNumber, unsigned int noteNumber) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 0, noteNumber, 0, 0, 0); +} + +int sceSdHdGetSplitBlockAddrByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, sceHardSynthSplitBlock **ptr) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 1, noteNumber, 0, 0, (void **)ptr); +} + +int sceSdHdGetSplitBlockByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, SceSdHdSplitBlock *param) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 2, noteNumber, 0, 0, (void **)param); +} + +int sceSdHdGetSampleSetParamCountByNote(void *buffer, unsigned int programNumber, unsigned int noteNumber) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 3, noteNumber, 0, 0, 0); +} + +int sceSdHdGetSampleSetParamAddrByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, sceHardSynthSampleSetParam **ptr) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 4, noteNumber, 0, 0, (void **)ptr); +} + +int sceSdHdGetSampleSetParamByNote( + void *buffer, unsigned int programNumber, unsigned int noteNumber, SceSdHdSampleSetParam *param) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 5, noteNumber, 0, 0, (void **)param); +} + +int sceSdHdGetSampleParamCountByNoteVelocity( + void *buffer, unsigned int programNumber, unsigned int noteNumber, unsigned int velocity, unsigned int mode) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 6, noteNumber, velocity, mode, 0); +} + +int sceSdHdGetSampleParamAddrByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + sceHardSynthSampleParam **ptr) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 7, noteNumber, velocity, mode, (void **)ptr); +} + +int sceSdHdGetSampleParamByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + SceSdHdSampleParam *param) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 8, noteNumber, velocity, mode, (void **)param); +} + +int sceSdHdGetVAGInfoParamCountByNoteVelocity( + void *buffer, unsigned int programNumber, unsigned int noteNumber, unsigned int velocity, unsigned int mode) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 9, noteNumber, velocity, mode, 0); +} + +int sceSdHdGetVAGInfoParamAddrByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + sceHardSynthVagParam **ptr) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 0xA, noteNumber, velocity, mode, (void **)ptr); +} + +int sceSdHdGetVAGInfoParamByNoteVelocity( + void *buffer, + unsigned int programNumber, + unsigned int noteNumber, + unsigned int velocity, + unsigned int mode, + SceSdHdVAGInfoParam *param) +{ + return do_get_common_block_ptr_note(buffer, programNumber, 0xB, noteNumber, velocity, mode, (void **)param); +} + +int sceSdHdGetSampleParamCountByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 6, velocity, mode, 0); +} + +int sceSdHdGetSampleParamAddrByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, sceHardSynthSampleParam **ptr) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 7, velocity, mode, (void **)ptr); +} + +int sceSdHdGetSampleParamByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, SceSdHdSampleParam *param) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 8, velocity, mode, (void **)param); +} + +int sceSdHdGetVAGInfoParamCountByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 9, velocity, mode, 0); +} + +int sceSdHdGetVAGInfoParamAddrByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, sceHardSynthVagParam **ptr) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 0xA, velocity, mode, (void **)ptr); +} + +int sceSdHdGetVAGInfoParamByVelocity( + void *buffer, unsigned int sampleSetNumber, unsigned int velocity, unsigned int mode, SceSdHdVAGInfoParam *param) +{ + return do_get_common_block_ptr(buffer, sampleSetNumber, 0xB, velocity, mode, (void **)param); +} + +int sceSdHdGetVAGInfoParamAddrBySampleNumber(void *buffer, unsigned int sampleNumber, sceHardSynthVagParam **ptr) +{ + int result; + sceHardSynthSampleParam *p_sampleparam; + + result = sceSdHdGetSampleParamAddr(buffer, sampleNumber, &p_sampleparam); + if ( result ) + return result; + if ( p_sampleparam->VagIndex == 0xFFFF ) + return (int)0x81039019; + return sceSdHdGetVAGInfoParamAddr(buffer, p_sampleparam->VagIndex, ptr); +} + +int sceSdHdGetVAGInfoParamBySampleNumber(void *buffer, unsigned int sampleNumber, SceSdHdVAGInfoParam *param) +{ + int result; + sceHardSynthVagParam *p_vagparam; + + result = sceSdHdGetVAGInfoParamAddrBySampleNumber(buffer, sampleNumber, &p_vagparam); + if ( result ) + return result; + do_copy_to_sdhd_vag_info_param( + param, do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr), p_vagparam); + return 0; +} + +int sceSdHdGetSplitBlockNumberBySplitNumber(void *buffer, unsigned int programNumber, unsigned int splitNumber) +{ + int result; + int i; + sceHardSynthSplitBlock *splitblock; + sceHardSynthProgramParam *p_programparam; + + result = sceSdHdGetProgramParamAddr(buffer, programNumber, &p_programparam); + if ( result ) + return result; + if ( p_programparam->splitBlockAddr == 0xFFFFFFFF ) + return (int)0x81039009; + splitblock = (sceHardSynthSplitBlock *)((char *)p_programparam + p_programparam->splitBlockAddr); + for ( i = 0; i < p_programparam->nSplit; i += 1 ) + { + if ( splitNumber == splitblock->splitNumber ) + return i; + splitblock = (sceHardSynthSplitBlock *)((char *)splitblock + p_programparam->sizeSplitBlock); + } + return (int)0x81039020; +} + +int sceSdHdGetVAGSize(void *buffer, unsigned int vagInfoNumber) +{ + int result; + sceHardSynthVagParam *p_vagparam; + + result = sceSdHdGetVAGInfoParamAddr(buffer, vagInfoNumber, &p_vagparam); + if ( result ) + return result; + return (int)do_get_vag_size((sceHardSynthVersionChunk *)buffer, &p_vagparam->vagOffsetAddr); +} + +int sceSdHdGetSplitBlockCount(void *buffer, unsigned int programNumber) +{ + int result; + sceHardSynthProgramParam *p_programparam; + + result = sceSdHdGetProgramParamAddr(buffer, programNumber, &p_programparam); + if ( result ) + return result; + return p_programparam->nSplit; +} + +int sceSdHdGetMaxSplitBlockCount(void *buffer) +{ + int curminval; + unsigned int retres; + unsigned int i; + unsigned int j; + int curval1; + int curval2; + sceHardSynthProgramParam *p_programparam; + sceHardSynthSplitBlock *p_splitblock; + + curminval = 0; + retres = (unsigned int)sceSdHdGetMaxProgramNumber(buffer); + if ( (retres & 0x80000000) != 0 ) + return 0; + for ( i = 0; i < retres; i += 1 ) + { + if ( !sceSdHdGetProgramParamAddr(buffer, i, &p_programparam) ) + { + for ( j = 0; j < p_programparam->nSplit; j += 1 ) + { + if ( !sceSdHdGetSplitBlockAddr(buffer, i, j, &p_splitblock) ) + { + curval1 = sceSdHdGetSplitBlockCountByNote(buffer, i, p_splitblock->splitRangeLow & 0x7F); + curminval = (curminval < curval1) ? curval1 : curminval; + curval2 = sceSdHdGetSplitBlockCountByNote(buffer, i, p_splitblock->splitRangeHigh & 0x7F); + curminval = (curminval < curval2) ? curval2 : curminval; + } + } + } + } + return curminval; +} + +int sceSdHdGetMaxSampleSetParamCount(void *buffer) +{ + int curminval; + unsigned int retres; + unsigned int i; + unsigned int j; + int curval1; + int curval2; + sceHardSynthProgramParam *p_programparam; + sceHardSynthSplitBlock *p_splitblock; + + curminval = 0; + retres = (unsigned int)sceSdHdGetMaxProgramNumber(buffer); + if ( (retres & 0x80000000) != 0 ) + return 0; + for ( i = 0; i < retres; i += 1 ) + { + if ( !sceSdHdGetProgramParamAddr(buffer, i, &p_programparam) ) + { + for ( j = 0; j < p_programparam->nSplit; j += 1 ) + { + if ( !sceSdHdGetSplitBlockAddr(buffer, i, j, &p_splitblock) ) + { + curval1 = sceSdHdGetSampleSetParamCountByNote(buffer, i, p_splitblock->splitRangeLow & 0x7F); + curminval = (curminval < curval1) ? curval1 : curminval; + curval2 = sceSdHdGetSampleSetParamCountByNote(buffer, i, p_splitblock->splitRangeHigh & 0x7F); + curminval = (curminval < curval2) ? curval2 : curminval; + } + } + } + } + return curminval; +} + +int sceSdHdGetMaxSampleParamCount(void *buffer) +{ + int curminval; + unsigned int retres; + unsigned int i; + unsigned int j; + unsigned int k; + int curval1; + int curval2; + int curval3; + int curval4; + sceHardSynthProgramParam *p_programparam; + sceHardSynthSplitBlock *p_splitblock; + sceHardSynthSampleSetParam *p_samplesetparam; + sceHardSynthSampleParam *p_sampleparam; + + curminval = 0; + retres = (unsigned int)sceSdHdGetMaxProgramNumber(buffer); + if ( (retres & 0x80000000) != 0 ) + return 0; + for ( i = 0; i < retres; i += 1 ) + { + if ( !sceSdHdGetProgramParamAddr(buffer, i, &p_programparam) ) + { + for ( j = 0; j < p_programparam->nSplit; j += 1 ) + { + if ( + !sceSdHdGetSplitBlockAddr(buffer, i, j, &p_splitblock) + && !sceSdHdGetSampleSetParamAddr(buffer, p_splitblock->sampleSetIndex, &p_samplesetparam) ) + { + for ( k = 0; k < p_samplesetparam->nSample; k += 1 ) + { + if ( !sceSdHdGetSampleParamAddr( + buffer, + (unsigned int)sceSdHdGetSampleNumberBySampleIndex(buffer, p_splitblock->sampleSetIndex, k), + &p_sampleparam) ) + { + curval1 = sceSdHdGetSampleParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeLow & 0x7F, p_sampleparam->velRangeLow & 0x7F, 1u); + curminval = (curminval < curval1) ? curval1 : curminval; + curval2 = sceSdHdGetSampleParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeLow & 0x7F, p_sampleparam->velRangeHigh & 0x7F, 1u); + curminval = (curminval < curval2) ? curval2 : curminval; + curval3 = sceSdHdGetSampleParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeHigh & 0x7F, p_sampleparam->velRangeLow & 0x7F, 1u); + curminval = (curminval < curval3) ? curval3 : curminval; + curval4 = sceSdHdGetSampleParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeHigh & 0x7F, p_sampleparam->velRangeHigh & 0x7F, 1u); + curminval = (curminval < curval4) ? curval4 : curminval; + } + } + } + } + } + } + return curminval; +} + +int sceSdHdGetMaxVAGInfoParamCount(void *buffer) +{ + int curminval; + unsigned int retres; + unsigned int i; + unsigned int j; + unsigned int k; + int curval1; + int curval2; + int curval3; + int curval4; + sceHardSynthProgramParam *p_programparam; + sceHardSynthSplitBlock *p_splitblock; + sceHardSynthSampleSetParam *p_samplesetparam; + sceHardSynthSampleParam *p_sampleparam; + + curminval = 0; + retres = (unsigned int)sceSdHdGetMaxProgramNumber(buffer); + if ( (retres & 0x80000000) != 0 ) + return 0; + for ( i = 0; i < retres; i += 1 ) + { + if ( !sceSdHdGetProgramParamAddr(buffer, i, &p_programparam) ) + { + for ( j = 0; j < p_programparam->nSplit; j += 1 ) + { + if ( + !sceSdHdGetSplitBlockAddr(buffer, i, j, &p_splitblock) + && !sceSdHdGetSampleSetParamAddr(buffer, p_splitblock->sampleSetIndex, &p_samplesetparam) ) + { + for ( k = 0; k < p_samplesetparam->nSample; k += 1 ) + { + if ( !sceSdHdGetSampleParamAddr( + buffer, + (unsigned int)sceSdHdGetSampleNumberBySampleIndex(buffer, p_splitblock->sampleSetIndex, k), + &p_sampleparam) ) + { + curval1 = sceSdHdGetVAGInfoParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeLow & 0x7F, p_sampleparam->velRangeLow & 0x7F, 1u); + curminval = (curminval < curval1) ? curval1 : curminval; + curval2 = sceSdHdGetVAGInfoParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeLow & 0x7F, p_sampleparam->velRangeHigh & 0x7F, 1u); + curminval = (curminval < curval2) ? curval2 : curminval; + curval3 = sceSdHdGetVAGInfoParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeHigh & 0x7F, p_sampleparam->velRangeLow & 0x7F, 1u); + curminval = (curminval < curval3) ? curval3 : curminval; + curval4 = sceSdHdGetVAGInfoParamCountByNoteVelocity( + buffer, i, p_splitblock->splitRangeHigh & 0x7F, p_sampleparam->velRangeHigh & 0x7F, 1u); + curminval = (curminval < curval4) ? curval4 : curminval; + } + } + } + } + } + } + return curminval; +} + +int sceSdHdModifyVelocity(unsigned int curveType, int velocity) +{ + switch ( curveType ) + { + case 1u: + return 128 - velocity; + case 2u: + velocity = velocity * velocity / 0x7F; + return velocity ? velocity : 1; + case 3u: + velocity = velocity * velocity / 0x7F; + velocity = velocity ? velocity : 1; + return 128 - velocity; + case 4u: + velocity = (128 - velocity) * (128 - velocity); + velocity = (velocity / 0x7F) & 0x3FFFFFF; + velocity = velocity ? velocity : 1; + return 128 - velocity; + case 5u: + velocity = 128 - velocity; + velocity = velocity * velocity / 0x7F; + return velocity ? velocity : 1; + default: + return velocity; + } +} + +int sceSdHdModifyVelocityLFO(unsigned int curveType, int velocity, int center) +{ + int calc5; + int calcb; + + center = (center >= 0) ? ((center >= 128) ? 127 : center) : 0; + velocity = (velocity >= 0) ? ((velocity >= 128) ? 127 : velocity) : 0; + calc5 = 0; + switch ( curveType ) + { + case 0u: + default: + calc5 = (velocity - center) << 16; + calc5 = (calc5 / 126) - (int)((unsigned int)calc5 >> 31); + break; + case 1u: + calc5 = (center - velocity) << 16; + calc5 = (calc5 / 126) - (int)((unsigned int)calc5 >> 31); + break; + case 2u: + calc5 = ((velocity - 1) << 15) / 126 * (((velocity - 1) << 15) / 126) + - ((center - 1) << 15) / 126 * (((center - 1) << 15) / 126); + calc5 = (calc5 < 0) ? ((calc5 + 0x3FFF) >> 14) : (calc5 >> 14); + break; + case 3u: + calc5 = ((velocity - 1) << 15) / 126 * (((velocity - 1) << 15) / 126) / -16384 + - ((center - 1) << 15) / 126 * (((center - 1) << 15) / 126) / -16384; + break; + case 4u: + calc5 = (0x10000 - ((center - 1) << 15) / 126) * (0x10000 - ((center - 1) << 15) / 126) / 0x4000 + - (0x10000 - ((velocity - 1) << 15) / 126) * (0x10000 - ((velocity - 1) << 15) / 126) / 0x4000; + break; + case 5u: + calc5 = (0x10000 - ((velocity - 1) << 15) / 126) * (0x10000 - ((velocity - 1) << 15) / 126) / 0x4000 + - (0x10000 - ((center - 1) << 15) / 126) * (0x10000 - ((center - 1) << 15) / 126) / 0x4000; + break; + case 6u: + if ( velocity == center ) + break; + calc5 = (center >= velocity) ? (center - 1) : (127 - center); + calcb = (velocity - center) << 16; + if ( !calc5 ) + __builtin_trap(); + if ( calc5 == -1 && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = calcb / calc5; + break; + case 7u: + if ( velocity == center ) + break; + calc5 = (center >= velocity) ? (center - 1) : (127 - center); + calcb = (center - velocity) << 16; + if ( !calc5 ) + __builtin_trap(); + if ( calc5 == -1 && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = calcb / calc5; + break; + case 8u: + if ( velocity == center ) + break; + calcb = (velocity - center) << 15; + if ( center >= velocity ) + { + if ( center == 1 ) + __builtin_trap(); + if ( !center && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = calcb / (center - 1) * (calcb / (center - 1)) / -16384; + } + else + { + calc5 = 127 - center; + if ( 127 == center ) + __builtin_trap(); + if ( calc5 == -1 && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = calcb / calc5 * (calcb / calc5); + calc5 = (calc5 < 0) ? ((calc5 + 0x3FFF) >> 14) : (calc5 >> 14); + } + break; + case 9u: + if ( velocity == center ) + break; + calcb = (velocity - center) << 15; + if ( center >= velocity ) + { + if ( center == 1 ) + __builtin_trap(); + if ( !center && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = (calcb / (center - 1) + 0x8000) * (calcb / (center - 1) + 0x8000) / 0x4000 - 0x10000; + } + else + { + calc5 = 127 - center; + if ( 127 == center ) + __builtin_trap(); + if ( calc5 == -1 && (unsigned int)calcb == 0x80000000 ) + __builtin_trap(); + calc5 = (0x8000 - calcb / calc5) * (0x8000 - calcb / calc5); + calc5 = 0x10000 - ((calc5 < 0) ? ((calc5 + 0x3FFF) >> 14) : (calc5 >> 14)); + } + break; + } + return (calc5 < -65536) ? -65536 : ((calc5 > 0xFFFF) ? 0xFFFF : calc5); +} + +int sceSdHdGetValidProgramNumberCount(void *buffer) +{ + int validcnt; + int result; + unsigned int i; + struct sdhd_info dinfo; + + validcnt = 0; + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_prog_chunk(buffer, &dinfo); + if ( result ) + return result; + for ( i = 0; dinfo.m_prog->maxProgramNumber >= i; i += 1 ) + { + if ( dinfo.m_prog->programOffsetAddr[i] != 0xFFFFFFFF ) + validcnt += 1; + } + return validcnt; +} + +int sceSdHdGetValidProgramNumber(void *buffer, unsigned int *ptr) +{ + int validcnt; + int result; + unsigned int i; + struct sdhd_info dinfo; + + validcnt = 0; + result = (int)do_get_vers_head_chunk((sceHardSynthVersionChunk *)buffer, &dinfo); + if ( result ) + return result; + result = (int)do_get_prog_chunk(buffer, &dinfo); + if ( result ) + return result; + for ( i = 0; dinfo.m_prog->maxProgramNumber >= i; i += 1 ) + { + if ( dinfo.m_prog->programOffsetAddr[i] != 0xFFFFFFFF ) + { + ptr[validcnt] = i; + validcnt += 1; + } + } + return validcnt; +} + +int sceSdHdGetSampleNumberBySampleIndex(void *buffer, unsigned int sampleSetNumber, unsigned int sampleIndexNumber) +{ + int result; + sceHardSynthSampleSetParam *p_samplesetparam; + + result = sceSdHdGetSampleSetParamAddr(buffer, sampleSetNumber, &p_samplesetparam); + if ( result ) + return result; + return ((unsigned int)p_samplesetparam->nSample - 1 < sampleIndexNumber) ? + 0x9006 : + p_samplesetparam->sampleIndex[sampleIndexNumber]; +} + +#ifdef _IOP +int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi) +{ + int regres; + int state; + + (void)av; + (void)startaddr; + if ( ac < 0 ) + { + CpuSuspendIntr(&state); + regres = ReleaseLibraryEntries(&_exp_sdhd); + CpuResumeIntr(state); + return (!regres) ? MODULE_NO_RESIDENT_END : MODULE_REMOVABLE_END; + } + CpuSuspendIntr(&state); + regres = RegisterLibraryEntries(&_exp_sdhd); + CpuResumeIntr(state); + if ( regres ) + return MODULE_NO_RESIDENT_END; +#if 0 + return MODULE_REMOVABLE_END; +#else + if ( mi && ((mi->newflags & 2) != 0) ) + mi->newflags |= 0x10; + return MODULE_RESIDENT_END; +#endif +} +#endif From 3393e9ab66391f0fa606ba5bd79a45af3909e2bb Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Mon, 1 Dec 2025 09:02:27 -0600 Subject: [PATCH 2/3] add: Implementation of sdsq module --- iop/sound/sdsq/Makefile | 21 ++ iop/sound/sdsq/README.md | 15 + iop/sound/sdsq/include/sdsq.h | 109 ++++++ iop/sound/sdsq/src/exports.tab | 21 ++ iop/sound/sdsq/src/imports.lst | 14 + iop/sound/sdsq/src/irx_imports.h | 24 ++ iop/sound/sdsq/src/sdsq.c | 594 +++++++++++++++++++++++++++++++ 7 files changed, 798 insertions(+) create mode 100644 iop/sound/sdsq/Makefile create mode 100644 iop/sound/sdsq/README.md create mode 100644 iop/sound/sdsq/include/sdsq.h create mode 100644 iop/sound/sdsq/src/exports.tab create mode 100644 iop/sound/sdsq/src/imports.lst create mode 100644 iop/sound/sdsq/src/irx_imports.h create mode 100644 iop/sound/sdsq/src/sdsq.c diff --git a/iop/sound/sdsq/Makefile b/iop/sound/sdsq/Makefile new file mode 100644 index 000000000000..977d20eb41b8 --- /dev/null +++ b/iop/sound/sdsq/Makefile @@ -0,0 +1,21 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_BIN ?= sdsq.irx + +IOP_IMPORT_INCS += \ + system/intrman \ + system/loadcore \ + system/sysclib + +IOP_OBJS = sdsq.o exports.o imports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/sound/sdsq/README.md b/iop/sound/sdsq/README.md new file mode 100644 index 000000000000..3d47597d1738 --- /dev/null +++ b/iop/sound/sdsq/README.md @@ -0,0 +1,15 @@ +# Sound data (SQ file) access library + +This module provides functions to access sequenced music stored in SQ files. + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `sdsq` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, use `LoadModule` or \ +`LoadModuleBuffer` with no arguments. diff --git a/iop/sound/sdsq/include/sdsq.h b/iop/sound/sdsq/include/sdsq.h new file mode 100644 index 000000000000..6da439476764 --- /dev/null +++ b/iop/sound/sdsq/include/sdsq.h @@ -0,0 +1,109 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifndef _SDSQ_H +#define _SDSQ_H + +#ifdef _IOP +#include +#endif + +typedef struct sceSeqMidiCompBlock_ +{ + u16 compOption; + u16 compTableSize; + u8 compTable[]; +} sceSeqMidiCompBlock; + +typedef struct sceSeqMidiDataBlock_ +{ + unsigned int sequenceDataOffset; + u16 Division; + sceSeqMidiCompBlock compBlock[]; +} sceSeqMidiDataBlock; + +typedef struct SceSdSqMidiData_ +{ + u32 readStatus; + u32 midiNumber; + sceSeqMidiDataBlock *midiData; + u32 offset; + u32 nextOffset; + u32 division; + u32 compMode; + u32 compTableSize; + u32 deltaTime; + u8 lastStatus; + u8 reserve[3]; + u32 messageLength; + u8 message[8]; + u32 originalMessageLength; + u8 originalMessage[12]; +} SceSdSqMidiData; + +typedef struct SceSdSqSongData_ +{ + u32 readStatus; + u32 songNumber; + void *topAddr; + u32 offset; + u32 nextOffset; + u8 message[3]; + u8 reserve; +} SceSdSqSongData; + +struct SceSdSqCompTableData_ +{ + u8 status; + u8 data; +}; + +typedef struct SceSdSqCompTableData_ SceSdSqCompTableData; +typedef struct SceSdSqCompTableData_ SceSdSqPolyKeyData; + +typedef struct SceSdSqCompTableNoteOnEvent_ +{ + u8 status; + u8 note; + u8 velocity; + u8 reserve; +} SceSdSqCompTableNoteOnEvent; + +extern int sceSdSqGetMaxMidiNumber(void *addr); +extern int sceSdSqGetMaxSongNumber(void *addr); +extern int sceSdSqInitMidiData(void *addr, u32 midiNumber, SceSdSqMidiData *midiData); +extern int sceSdSqReadMidiData(SceSdSqMidiData *midiData); +extern int sceSdSqInitSongData(void *addr, u32 songNumber, SceSdSqSongData *songData); +extern int sceSdSqReadSongData(SceSdSqSongData *songData); +extern int sceSdSqGetMaxCompTableIndex(void *addr, u32 midiNumber); +extern int sceSdSqGetCompTableOffset(void *addr, u32 midiNumber, u32 *offset); +extern int sceSdSqGetCompTableDataByIndex(void *addr, u32 midiNumber, u32 compTableIndex, SceSdSqCompTableData *data); +extern int sceSdSqGetNoteOnEventByPolyKeyPress( + void *addr, u32 midiNumber, const SceSdSqPolyKeyData *pData, SceSdSqCompTableNoteOnEvent *kData); +extern int sceSdSqCopyMidiData(SceSdSqMidiData *to, const SceSdSqMidiData *from); +extern int sceSdSqCopySongData(SceSdSqSongData *to, const SceSdSqSongData *from); + +#define sdsq_IMPORTS_start DECLARE_IMPORT_TABLE(sdsq, 1, 1) +#define sdsq_IMPORTS_end END_IMPORT_TABLE + +#define I_sceSdSqGetMaxMidiNumber DECLARE_IMPORT(4, sceSdSqGetMaxMidiNumber) +#define I_sceSdSqGetMaxSongNumber DECLARE_IMPORT(5, sceSdSqGetMaxSongNumber) +#define I_sceSdSqInitMidiData DECLARE_IMPORT(6, sceSdSqInitMidiData) +#define I_sceSdSqReadMidiData DECLARE_IMPORT(7, sceSdSqReadMidiData) +#define I_sceSdSqInitSongData DECLARE_IMPORT(8, sceSdSqInitSongData) +#define I_sceSdSqReadSongData DECLARE_IMPORT(9, sceSdSqReadSongData) +#define I_sceSdSqGetMaxCompTableIndex DECLARE_IMPORT(10, sceSdSqGetMaxCompTableIndex) +#define I_sceSdSqGetCompTableOffset DECLARE_IMPORT(11, sceSdSqGetCompTableOffset) +#define I_sceSdSqGetCompTableDataByIndex DECLARE_IMPORT(12, sceSdSqGetCompTableDataByIndex) +#define I_sceSdSqGetNoteOnEventByPolyKeyPress DECLARE_IMPORT(13, sceSdSqGetNoteOnEventByPolyKeyPress) +#define I_sceSdSqCopyMidiData DECLARE_IMPORT(14, sceSdSqCopyMidiData) +#define I_sceSdSqCopySongData DECLARE_IMPORT(15, sceSdSqCopySongData) + +#endif diff --git a/iop/sound/sdsq/src/exports.tab b/iop/sound/sdsq/src/exports.tab new file mode 100644 index 000000000000..efa7ee9cccfe --- /dev/null +++ b/iop/sound/sdsq/src/exports.tab @@ -0,0 +1,21 @@ + +DECLARE_EXPORT_TABLE(sdsq, 1, 1) + DECLARE_EXPORT(_start) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(_retonly) + DECLARE_EXPORT(sceSdSqGetMaxMidiNumber) + DECLARE_EXPORT(sceSdSqGetMaxSongNumber) + DECLARE_EXPORT(sceSdSqInitMidiData) + DECLARE_EXPORT(sceSdSqReadMidiData) + DECLARE_EXPORT(sceSdSqInitSongData) + DECLARE_EXPORT(sceSdSqReadSongData) + DECLARE_EXPORT(sceSdSqGetMaxCompTableIndex) + DECLARE_EXPORT(sceSdSqGetCompTableOffset) + DECLARE_EXPORT(sceSdSqGetCompTableDataByIndex) + DECLARE_EXPORT(sceSdSqGetNoteOnEventByPolyKeyPress) + DECLARE_EXPORT(sceSdSqCopyMidiData) + DECLARE_EXPORT(sceSdSqCopySongData) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/sound/sdsq/src/imports.lst b/iop/sound/sdsq/src/imports.lst new file mode 100644 index 000000000000..99bf8bd8bb00 --- /dev/null +++ b/iop/sound/sdsq/src/imports.lst @@ -0,0 +1,14 @@ + +intrman_IMPORTS_start +I_CpuSuspendIntr +I_CpuResumeIntr +intrman_IMPORTS_end + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_ReleaseLibraryEntries +loadcore_IMPORTS_end + +sysclib_IMPORTS_start +I_memcpy +sysclib_IMPORTS_end diff --git a/iop/sound/sdsq/src/irx_imports.h b/iop/sound/sdsq/src/irx_imports.h new file mode 100644 index 000000000000..1d101732cb10 --- /dev/null +++ b/iop/sound/sdsq/src/irx_imports.h @@ -0,0 +1,24 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +# +# Defines all IRX imports. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include + +/* Please keep these in alphabetical order! */ + +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/sound/sdsq/src/sdsq.c b/iop/sound/sdsq/src/sdsq.c new file mode 100644 index 000000000000..6e6e2c663185 --- /dev/null +++ b/iop/sound/sdsq/src/sdsq.c @@ -0,0 +1,594 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifdef _IOP +#include "irx_imports.h" +#else +#include +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#endif +#include + +#ifdef _IOP +IRX_ID("Sound_Data_SQ", 2, 1); +#endif +// Based on the module from SCE SDK 3.1.0. + +struct sceHardSynthVersionChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + u16 reserved; + u8 versionMajor; + u8 versionMinor; +}; +typedef struct sceHardSynthVersionChunk_ sceHardSynthVersionChunk; +typedef struct sceHardSynthVersionChunk_ sceSeqVersionChunk; + +typedef struct sceSeqHeaderChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int fileSize; + unsigned int songChunkAddr; + unsigned int midiChunkAddr; + unsigned int seSequenceChunkAddr; + unsigned int seSongChunkAddr; +} sceSeqHeaderChunk; + +typedef struct sceSeqMidiChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxMidiNumber; + unsigned int midiOffsetAddr[]; +} sceSeqMidiChunk; + +typedef struct sceSeqSongChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxSongNumber; + unsigned int songOffsetAddr[]; +} sceSeqSongChunk; + +typedef struct sceSeqSeSequenceChunk_ +{ + unsigned int Creator; + unsigned int Type; + unsigned int chunkSize; + unsigned int maxSeSequenceSetNumber; + unsigned int tableOffset; + u8 seSequenceMasterVolume; + char seSequenceMasterPanpot; + u16 seSequenceMasterTimeScale; + unsigned int dmy0; + unsigned int dmy1; + unsigned int seSequenceSetOffsetAddr[]; +} sceSeqSeSequenceChunk; + +struct sdsq_info +{ + sceSeqVersionChunk *m_vers; + sceSeqHeaderChunk *m_sequ; + sceSeqMidiChunk *m_midi; + sceSeqSongChunk *m_song; +}; + +#ifdef _IOP +extern struct irx_export_table _exp_sdsq; +#endif + +static unsigned int do_get_vers_sequ_chunk(sceSeqVersionChunk *indata, struct sdsq_info *dinfo) +{ + dinfo->m_vers = 0; + dinfo->m_sequ = 0; + dinfo->m_midi = 0; + dinfo->m_song = 0; + dinfo->m_vers = indata; + if ( indata->Creator != 0x53434549 || indata->Type != 0x56657273 ) + { + dinfo->m_vers = 0; + return 0x8104000E; + } + if ( (indata->chunkSize & 0x80000000) ) + { + dinfo->m_vers = 0; + return 0x8104002F; + } + dinfo->m_sequ = (sceSeqHeaderChunk *)((char *)indata + indata->chunkSize); + if ( dinfo->m_sequ->Creator != 0x53434549 || dinfo->m_sequ->Type != 0x53657175 ) + { + dinfo->m_vers = 0; + dinfo->m_sequ = 0; + return 0x8104002F; + } + return 0; +} + +static unsigned int do_get_midi_chunk(void *indata, struct sdsq_info *dinfo) +{ + if ( dinfo->m_sequ->midiChunkAddr == 0xFFFFFFFF ) + return 0x81049024; + if ( (dinfo->m_sequ->midiChunkAddr & 0x80000000) ) + return 0x8104002F; + dinfo->m_midi = (sceSeqMidiChunk *)((char *)indata + dinfo->m_sequ->midiChunkAddr); + if ( dinfo->m_midi->Creator != 0x53434549 || dinfo->m_midi->Type != 0x4D696469 ) + { + dinfo->m_midi = 0; + return 0x8104002F; + } + return 0; +} + +static unsigned int do_get_song_chunk(void *indata, struct sdsq_info *dinfo) +{ + if ( dinfo->m_sequ->songChunkAddr == 0xFFFFFFFF ) + return 0x81049025; + if ( (dinfo->m_sequ->songChunkAddr & 0x80000000) ) + return 0x8104002F; + dinfo->m_song = (sceSeqSongChunk *)((char *)indata + dinfo->m_sequ->songChunkAddr); + if ( dinfo->m_song->Creator != 0x53434549 || dinfo->m_song->Type != 0x536F6E67 ) + { + dinfo->m_song = 0; + return 0x8104002F; + } + return 0; +} + +static unsigned int do_get_midi_data_block(void *indata, unsigned int idx, sceSeqMidiDataBlock **datablk) +{ + unsigned int result; + struct sdsq_info dinfo; + + result = do_get_vers_sequ_chunk((sceSeqVersionChunk *)indata, &dinfo); + if ( result ) + return result; + result = do_get_midi_chunk(indata, &dinfo); + if ( result ) + return result; + if ( dinfo.m_midi->maxMidiNumber < idx ) + return 0x81049026; + if ( dinfo.m_midi->midiOffsetAddr[idx] == 0xFFFFFFFF ) + return 0x81049026; + *datablk = (sceSeqMidiDataBlock *)((char *)dinfo.m_midi + dinfo.m_midi->midiOffsetAddr[idx]); + return 0; +} + +int sceSdSqGetMaxMidiNumber(void *addr) +{ + int result; + struct sdsq_info dinfo; + + result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo); + if ( result ) + return result; + result = (int)do_get_midi_chunk(addr, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_midi->maxMidiNumber; +} + +int sceSdSqGetMaxSongNumber(void *addr) +{ + int result; + struct sdsq_info dinfo; + + result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo); + if ( result ) + return result; + result = (int)do_get_song_chunk(addr, &dinfo); + if ( result ) + return result; + return (int)dinfo.m_song->maxSongNumber; +} + +int sceSdSqInitMidiData(void *addr, u32 midiNumber, SceSdSqMidiData *midiData) +{ + int result; + struct sdsq_info dinfo; + + result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo); + if ( result ) + return result; + result = (int)do_get_midi_chunk(addr, &dinfo); + if ( result ) + return result; + if ( dinfo.m_midi->maxMidiNumber < midiNumber ) + return (int)0x81049026; + if ( dinfo.m_midi->midiOffsetAddr[midiNumber] == 0xFFFFFFFF ) + return (int)0x81049026; + midiData->readStatus = 0; + midiData->midiNumber = midiNumber; + midiData->midiData = (sceSeqMidiDataBlock *)((char *)dinfo.m_midi + dinfo.m_midi->midiOffsetAddr[midiNumber]); + midiData->offset = 0; + midiData->nextOffset = midiData->midiData->sequenceDataOffset; + midiData->division = midiData->midiData->Division; + midiData->compMode = (midiData->nextOffset == 6) ? 0 : 1; + midiData->compTableSize = (midiData->nextOffset == 6) ? 0 : midiData->midiData->compBlock[0].compTableSize; + midiData->deltaTime = 0; + midiData->lastStatus = 0; + midiData->reserve[0] = 0; + midiData->reserve[1] = 0; + midiData->reserve[2] = 0; + midiData->messageLength = 1; + midiData->message[0] = 0; + midiData->message[1] = 0; + midiData->message[2] = 0; + midiData->message[3] = 0; + midiData->message[4] = 0; + midiData->message[5] = 0; + midiData->message[6] = 0; + midiData->message[7] = 0; + midiData->originalMessageLength = 1; + midiData->originalMessage[0] = 0; + midiData->originalMessage[1] = 0; + midiData->originalMessage[2] = 0; + midiData->originalMessage[3] = 0; + midiData->originalMessage[4] = 0; + midiData->originalMessage[5] = 0; + midiData->originalMessage[6] = 0; + midiData->originalMessage[7] = 0; + midiData->originalMessage[8] = 0; + midiData->originalMessage[9] = 0; + midiData->originalMessage[10] = 0; + midiData->originalMessage[11] = 0; + return 0; +} + +int sceSdSqReadMidiData(SceSdSqMidiData *midiData) +{ + char niceflag; + u8 cur_message; + sceSeqMidiDataBlock *midiData_1; + u32 nextOffset; + u8 lastStatus; + u8 *midiData_offs; + u32 midiData_curval1_1; + u8 midiData_curval2; + const u8 *midiData_offs_plusone; + u32 nextMessageLength; + u8 *currofssplusone; + u8 *someaddoffsone; + int endflg; + + endflg = 3; + niceflag = 0; + if ( midiData->readStatus ) + return (int)0x81048001; + if ( !midiData->originalMessageLength ) + { + midiData->readStatus = 2; + return (int)0x8104002F; + } + cur_message = midiData->originalMessage[midiData->originalMessageLength - 1]; + midiData_1 = midiData->midiData; + nextOffset = midiData->nextOffset; + lastStatus = midiData->lastStatus; + midiData->originalMessageLength = 0; + midiData->messageLength = 0; + midiData_offs = (u8 *)midiData_1 + nextOffset; + midiData->offset = nextOffset; + midiData_curval1_1 = 0; + if ( !(cur_message & 0x80) || lastStatus == 255 ) + { + u8 midiData_curval1; + + midiData_curval1 = *midiData_offs; + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + midiData->originalMessageLength += 1; + midiData_offs += 1; + midiData_curval1_1 = midiData_curval1 & 0x7F; + while ( midiData_curval1 & 0x80 ) + { + midiData_curval1 = *midiData_offs; + midiData_offs += 1; + midiData->originalMessage[midiData->originalMessageLength] = midiData_curval1; + midiData->originalMessageLength += 1; + midiData_curval1_1 = (midiData_curval1_1 << 7) + (midiData_curval1 & 0x7F); + } + } + midiData->deltaTime = midiData_curval1_1; + midiData_curval2 = *midiData_offs; + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + if ( (midiData_curval2 & 0x80) ) + { + midiData_offs += 1; + midiData->originalMessageLength += 1; + } + else + { + midiData_curval2 = lastStatus; + } + midiData->message[0] = midiData_curval2; + midiData->lastStatus = midiData_curval2; + midiData_offs_plusone = 0; + switch ( midiData_curval2 & 0xF0 ) + { + case 0x90: + case 0xB0: + case 0xE0: + { + endflg = 4; + break; + } + case 0x80: + case 0xC0: + case 0xD0: + { + break; + } + case 0xA0: + { + if ( !midiData->compMode ) + { + endflg = 4; + } + else + { + int someoffsx; + + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength]; + midiData->message[2] = 8 * (midiData->originalMessage[midiData->originalMessageLength] & 0xF); + midiData->originalMessageLength = midiData->originalMessageLength + 1; + someoffsx = 2 * ((midiData->message[0] & 0xF) | (midiData->message[1] & 0x70)); + midiData->message[1] = midiData->message[1] & 0x7F; + midiData_offs_plusone = midiData_offs + 1; + midiData->message[0] = *((u8 *)&midiData->midiData->compBlock[1].compOption + someoffsx); + midiData->message[1] = *((u8 *)&midiData->midiData->compBlock[1].compOption + someoffsx + 1); + midiData->messageLength = 3; + endflg = 1; + } + break; + } + case 0xF0: + { + int i; + u8 midiData_curval7; + int msg2ew; + + if ( midiData_curval2 != 255 ) + { + midiData->readStatus = 2; + return (int)0x8104002F; + } + midiData->messageLength = 1; + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength]; + midiData->messageLength = midiData->messageLength + 1; + midiData->originalMessageLength = midiData->originalMessageLength + 1; + someaddoffsone = midiData_offs + 1; + midiData_curval7 = *someaddoffsone; + midiData->originalMessage[midiData->originalMessageLength] = *someaddoffsone; + midiData->message[2] = midiData->originalMessage[midiData->originalMessageLength]; + midiData->messageLength = midiData->messageLength + 1; + midiData_offs_plusone = someaddoffsone + 1; + midiData->originalMessageLength += 1; + msg2ew = midiData_curval7; + for ( i = 1; msg2ew >= i; i += 1 ) + { + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs_plusone; + midiData_offs_plusone += 1; + midiData->message[i + 2] = midiData->originalMessage[midiData->originalMessageLength]; + msg2ew = midiData->message[2]; + midiData->messageLength += 1; + midiData->originalMessageLength += 1; + } + niceflag = 1; + if ( midiData->message[0] == 0xFF && midiData->message[1] == 0x2F && midiData->message[2] == 0x00 ) + midiData->readStatus = 1; + endflg = 1; + break; + } + default: + { + midiData->readStatus = 2; + return (int)0x8104002F; + } + } + nextMessageLength = 0; + if ( endflg >= 4 ) + { + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + midiData->message[1] = *midiData_offs; + midiData->originalMessageLength = midiData->originalMessageLength + 1; + currofssplusone = midiData_offs + 1; + midiData->originalMessage[midiData->originalMessageLength] = *currofssplusone; + midiData_offs_plusone = currofssplusone + 1; + midiData->message[2] = midiData->originalMessage[midiData->originalMessageLength]; + nextMessageLength = 3; + endflg = 2; + } + if ( endflg >= 3 ) + { + midiData->originalMessage[midiData->originalMessageLength] = *midiData_offs; + midiData_offs_plusone = midiData_offs + 1; + midiData->message[1] = midiData->originalMessage[midiData->originalMessageLength]; + nextMessageLength = 2; + } + if ( endflg >= 2 ) + { + midiData->messageLength = nextMessageLength; + midiData->originalMessageLength = midiData->originalMessageLength + 1; + } + if ( !niceflag ) + midiData->message[midiData->messageLength - 1] &= ~0x80u; + midiData->nextOffset = (u32)(midiData_offs_plusone - (u8 *)midiData->midiData); + return 0; +} + +int sceSdSqInitSongData(void *addr, u32 songNumber, SceSdSqSongData *songData) +{ + int result; + struct sdsq_info dinfo; + + result = (int)do_get_vers_sequ_chunk((sceSeqVersionChunk *)addr, &dinfo); + if ( result ) + return result; + result = (int)do_get_song_chunk(addr, &dinfo); + if ( result ) + return result; + if ( dinfo.m_song->maxSongNumber < songNumber ) + return (int)0x81049027; + if ( dinfo.m_song->songOffsetAddr[songNumber] == 0xFFFFFFFF ) + return (int)0x81049027; + songData->readStatus = 0; + songData->songNumber = songNumber; + songData->topAddr = (char *)(dinfo.m_song) + dinfo.m_song->songOffsetAddr[songNumber]; + songData->offset = 0; + songData->nextOffset = 0; + songData->message[0] = 0; + songData->message[1] = 0; + songData->message[2] = 0; + songData->reserve = 0; + return 0; +} + +int sceSdSqReadSongData(SceSdSqSongData *songData) +{ + const u8 *curOffset; + + if ( songData->readStatus ) + return (int)0x81048001; + curOffset = (u8 *)songData->topAddr + songData->nextOffset; + if ( (*curOffset & 0xF0) != 160 || (curOffset[1] & 0x80u) ) + { + songData->readStatus = 2; + return (int)0x8104002F; + } + songData->offset = songData->nextOffset; + songData->message[0] = *curOffset; + songData->message[1] = curOffset[1]; + songData->message[2] = curOffset[2]; + if ( songData->message[0] == 0xA0 && songData->message[1] == 0x7F && songData->message[2] == 0x7F ) + songData->readStatus = 1; + else + songData->nextOffset += 3; + return 0; +} + +int sceSdSqGetMaxCompTableIndex(void *addr, u32 midiNumber) +{ + int result; + sceSeqMidiDataBlock *dblk; + + result = (int)do_get_midi_data_block(addr, midiNumber, &dblk); + if ( result ) + return result; + if ( dblk->sequenceDataOffset == 6 ) + return (int)0x81049028; + return dblk->compBlock[0].compTableSize >> 1; +} + +int sceSdSqGetCompTableOffset(void *addr, u32 midiNumber, u32 *offset) +{ + int result; + sceSeqMidiDataBlock *dblk; + + result = (int)do_get_midi_data_block(addr, midiNumber, &dblk); + if ( result ) + return result; + if ( dblk->sequenceDataOffset == 6 ) + return (int)0x81049028; + *offset = (u32)((char *)dblk - (char *)addr) - 10; + return 0; +} + +int sceSdSqGetCompTableDataByIndex(void *addr, u32 midiNumber, u32 compTableIndex, SceSdSqCompTableData *data) +{ + int result; + sceSeqMidiDataBlock *dblk; + + result = (int)do_get_midi_data_block(addr, midiNumber, &dblk); + if ( result ) + return result; + if ( dblk->sequenceDataOffset == 6 ) + return (int)0x81049028; + if ( dblk->compBlock[0].compTableSize >> 1 < compTableIndex ) + return (int)0x81049029; + data->status = *((u8 *)&dblk->compBlock[1].compOption + (compTableIndex << 1)); + data->data = *((u8 *)&dblk->compBlock[1].compOption + (compTableIndex << 1) + 1); + return 0; +} + +int sceSdSqGetNoteOnEventByPolyKeyPress( + void *addr, u32 midiNumber, const SceSdSqPolyKeyData *pData, SceSdSqCompTableNoteOnEvent *kData) +{ + u32 compTableIndex; + int result; + SceSdSqCompTableData data; + + if ( (pData->status & 0xF0) != 160 ) + return (int)0x8104902A; + compTableIndex = (pData->status & 0xF) + (pData->data & 0xF0); + if ( compTableIndex >= 0x80 ) + return (int)0x8104902A; + result = sceSdSqGetCompTableDataByIndex(addr, midiNumber, compTableIndex, &data); + if ( result ) + return result; + kData->status = data.status; + kData->note = data.data; + kData->velocity = 8 * (pData->data & 0xF); + return 0; +} + +int sceSdSqCopyMidiData(SceSdSqMidiData *to, const SceSdSqMidiData *from) +{ + // The following structure copy was inlined + *to = *from; + return 0; +} + +int sceSdSqCopySongData(SceSdSqSongData *to, const SceSdSqSongData *from) +{ + // The following structure copy was inlined + *to = *from; + return 0; +} + +#ifdef _IOP +int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi) +{ + int regres; + int state; + + (void)av; + (void)startaddr; + if ( ac < 0 ) + { + CpuSuspendIntr(&state); + regres = ReleaseLibraryEntries(&_exp_sdsq); + CpuResumeIntr(state); + return (!regres) ? MODULE_NO_RESIDENT_END : MODULE_REMOVABLE_END; + } + CpuSuspendIntr(&state); + regres = RegisterLibraryEntries(&_exp_sdsq); + CpuResumeIntr(state); + if ( regres ) + return MODULE_NO_RESIDENT_END; +#if 0 + return MODULE_REMOVABLE_END; +#else + if ( mi && ((mi->newflags & 2) != 0) ) + mi->newflags |= 0x10; + return MODULE_RESIDENT_END; +#endif +} +#endif From e2190c8389ef80b8f96b66ff96c04df0658ca133 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Mon, 1 Dec 2025 09:02:33 -0600 Subject: [PATCH 3/3] buildsystem: Hook up newly-added modules to buildsystem --- iop/sound/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iop/sound/Makefile b/iop/sound/Makefile index 452670cf81ed..b355717c4876 100644 --- a/iop/sound/Makefile +++ b/iop/sound/Makefile @@ -15,7 +15,9 @@ SUBDIRS = \ libspu2 \ ps2snd \ rspu2drv \ - sdrdrv + sdhd \ + sdrdrv \ + sdsq include $(PS2SDKSRC)/Defs.make include $(PS2SDKSRC)/Rules.make