Revolution SDK work (#3091)

* Implement revolution/ax

Copied mostly unchanged from Petari

* Implement revolution/axfx

Copied mostly unchanged from Petari

* Implement revolution/arc

Copied mostly unchanged from Petari

* Implement revolution/mem

Copied mostly unchanged from Petari

* Implement revolution/tpl

Copied verbatim from Petari

* revolution/ipc matching (except small linking issue on ShieldD)

* revolution/pad/Pad matching

Largely copied from Petari with significant modifications

* Fix up ut_TextWriterBase symbols

* Fix homebuttonLib file names in Shield splits
This commit is contained in:
Max Roncace
2026-02-11 03:10:40 -05:00
committed by GitHub
parent b9de3375b4
commit 255705a4cd
40 changed files with 1976 additions and 393 deletions
+297
View File
@@ -0,0 +1,297 @@
#include <revolution/arc.h>
#include <revolution.h>
#include <locale>
/* this is here because it won't be inlined otherwise */
inline int tolower(int c) {
return ((c < 0) || (c >= 0x100)) ? c : (int) (_current_locale.ctype_cmpt_ptr->lower_map_ptr[c]);
}
typedef struct FSTEntry FSTEntry;
struct FSTEntry {
unsigned int isDirAndStringOff;
unsigned int parentOrPosition;
unsigned int nextEntryOrLength;
};
#define entryIsDir(fstStart, i) \
( ( ( fstStart[i].isDirAndStringOff & 0xFF000000 ) == 0 )? FALSE : TRUE )
#define stringOff(fstStart, i) \
( fstStart[i].isDirAndStringOff & 0x00FFFFFF )
#define parentDir(fstStart, i) \
( fstStart[i].parentOrPosition )
#define nextDir(fstStart, i) \
( fstStart[i].nextEntryOrLength )
#define filePosition(fstStart, i) \
( fstStart[i].parentOrPosition )
#define fileLength(fstStart, i) \
( fstStart[i].nextEntryOrLength )
BOOL ARCInitHandle(void* arcStart, ARCHandle* handle) {
FSTEntry* FSTEntries;
ARCHeader* arcHeader = (ARCHeader*)arcStart;
if (arcHeader->magic != 0x55AA382D) {
#if SDK_AUG2010
OSPanic(__FILE__, 0x4A, "ARCInitHandle: bad archive format");
#else
OSPanic(__FILE__, 0x47, "ARCInitHandle: bad archive format");
#endif
}
handle->archiveStartAddr = arcStart;
handle->FSTStart = FSTEntries = (void*)((u32)arcStart + arcHeader->fstStart);
handle->fileStart = (void*)((u32)arcStart + arcHeader->fileStart);
handle->entryNum = nextDir(FSTEntries, 0);
handle->FSTStringStart = (char*)&(FSTEntries[handle->entryNum]);
handle->FSTLength = (u32)arcHeader->fstSize;
handle->currDir = 0;
return TRUE;
}
BOOL ARCFastOpen(ARCHandle* handle, s32 entrynum, ARCFileInfo* af) {
FSTEntry* FSTEntries = (FSTEntry*)handle->FSTStart;
if ((entrynum < 0) || (entrynum >= handle->entryNum) || entryIsDir(FSTEntries, entrynum)) {
return FALSE;
}
af->handle = handle;
af->startOffset = filePosition(FSTEntries, entrynum);
af->length = fileLength(FSTEntries, entrynum);
return TRUE;
}
static BOOL isSame(const char* path, const char* string) {
while(*string != '\0') {
if (tolower(*path++) != tolower(*string++)) {
return FALSE;
}
}
if ((*path == '/') || (*path == '\0')) {
return TRUE;
}
return FALSE;
}
s32 ARCConvertPathToEntrynum(ARCHandle* handle, const char* pathPtr)
{
const char* ptr;
char* stringPtr;
BOOL isDir;
s32 length;
u32 dirLookAt;
u32 i;
const char* origPathPtr = pathPtr;
FSTEntry* FSTEntries;
dirLookAt = handle->currDir;
FSTEntries = (FSTEntry*)handle->FSTStart;
while (1) {
if (*pathPtr == '\0') {
return (s32)dirLookAt;
}
else if (*pathPtr == '/') {
dirLookAt = 0;
pathPtr++;
continue;
}
else if (*pathPtr == '.') {
if (*(pathPtr + 1) == '.') {
if (*(pathPtr + 2) == '/') {
dirLookAt = parentDir(FSTEntries, dirLookAt);
pathPtr += 3;
continue;
}
else if (*(pathPtr + 2) == '\0') {
return (s32)parentDir(FSTEntries, dirLookAt);
}
}
else if (*(pathPtr + 1) == '/') {
pathPtr += 2;
continue;
}
else if (*(pathPtr + 1) == '\0') {
return (s32)dirLookAt;
}
}
for(ptr = pathPtr; (*ptr != '\0') && (*ptr != '/'); ptr++);
isDir = (*ptr == '\0')? FALSE : TRUE;
length = (s32)(ptr - pathPtr);
ptr = pathPtr;
for(i = dirLookAt + 1; i < nextDir(FSTEntries, dirLookAt);
i = entryIsDir(FSTEntries, i)? nextDir(FSTEntries, i): (i+1) )
{
dot:
if ((entryIsDir(FSTEntries, i) == FALSE) && (isDir == TRUE)) {
continue;
}
stringPtr = handle->FSTStringStart + stringOff(FSTEntries, i);
if (*stringPtr == '.' && *(stringPtr + 1) == '\0') {
i++;
goto dot;
}
if (isSame(ptr, stringPtr) == TRUE) {
goto next_hier;
}
}
return -1;
next_hier:
if (!isDir) {
return (s32)i;
}
dirLookAt = i;
pathPtr += length + 1;
}
// the world ends if this is reached
}
static u32 myStrncpy(char* dest, char* src, u32 maxlen) {
u32 i = maxlen;
while ((i > 0) && (*src != 0)) {
*dest++ = *src++;
i--;
}
return (maxlen - i);
}
static u32 entryToPath(ARCHandle* handle, u32 entry, char* path, u32 maxlen) {
char* name;
u32 loc;
FSTEntry* FSTEntries = (FSTEntry*)handle->FSTStart;
if (entry == 0) {
return 0;
}
name = handle->FSTStringStart + stringOff(FSTEntries, entry);
loc = entryToPath(handle, parentDir(FSTEntries, entry), path, maxlen);
if (loc == maxlen) {
return loc;
}
*(path + loc++) = '/';
loc += myStrncpy(path + loc, name, maxlen - loc);
return loc;
}
static BOOL ARCConvertEntrynumToPath(ARCHandle* handle, s32 entrynum, char* path, u32 maxlen) {
u32 loc;
FSTEntry* FSTEntries = (FSTEntry*)handle->FSTStart;
loc = entryToPath(handle, (u32)entrynum, path, maxlen);
if (loc == maxlen) {
path[maxlen - 1] = '\0';
return FALSE;
}
if (entryIsDir(FSTEntries, entrynum)) {
if (loc == maxlen - 1) {
path[loc] = '\0';
return FALSE;
}
path[loc++] = '/';
}
path[loc] = '\0';
return TRUE;
}
static BOOL ARCGetCurrentDir(ARCHandle* handle, char* path, u32 maxlen) {
return ARCConvertEntrynumToPath(handle, (s32)handle->currDir, path, maxlen);
}
void* ARCGetStartAddrInMem(ARCFileInfo* af) {
ARCHandle* handle = af->handle;
return (void*)((u32)handle->archiveStartAddr + af->startOffset);
}
u32 ARCGetLength(ARCFileInfo* af) {
return af->length;
}
BOOL ARCClose(ARCFileInfo* af) {
return TRUE;
}
BOOL ARCChangeDir(ARCHandle* handle, const char* dirName) {
s32 entry;
FSTEntry* FSTEntries;
entry = ARCConvertPathToEntrynum(handle, dirName);
FSTEntries = (FSTEntry*)handle->FSTStart;
if ((entry < 0) || (entryIsDir(FSTEntries, entry) == FALSE)) {
return FALSE;
}
handle->currDir = (u32)entry;
return TRUE;
}
BOOL ARCOpenDir(ARCHandle* handle, const char* dirName, ARCDir* dir) {
s32 entry;
FSTEntry* FSTEntries;
entry = ARCConvertPathToEntrynum(handle, dirName);
FSTEntries = (FSTEntry*)handle->FSTStart;
if ((entry < 0) || (entryIsDir(FSTEntries, entry) == FALSE)) {
return FALSE;
}
dir->handle = handle;
dir->entryNum = (u32)entry;
dir->location = (u32)entry + 1;
dir->next = nextDir(FSTEntries, entry);
return TRUE;
}
BOOL ARCReadDir(ARCDir* dir, ARCDirEntry* dirent) {
u32 loc;
FSTEntry* FSTEntries;
ARCHandle* handle;
handle = dir->handle;
FSTEntries = (FSTEntry*)handle->FSTStart;
loc = dir->location;
retry:
if ((loc <= dir->entryNum) || (dir->next <= loc)) {
return FALSE;
}
dirent->handle = handle;
dirent->entryNum = loc;
dirent->isDir = entryIsDir(FSTEntries, loc);
dirent->name = handle->FSTStringStart + stringOff(FSTEntries, loc);
if (dirent->name[0] == '.' && dirent->name[1] == '\0') {
loc++;
goto retry;
}
dir->location = entryIsDir(FSTEntries, loc)? nextDir(FSTEntries, loc) : (loc+1);
return TRUE;
}
BOOL ARCCloseDir(ARCDir* dir) {
return TRUE;
}
+30
View File
@@ -0,0 +1,30 @@
#include <revolution/ax.h>
#include <revolution/os.h>
#include <cstring>
static u8 __clearAuxA[3];
static AXAuxCallback __AXCallbackAuxA;
static void* __AXContextAuxA;
void AXRegisterAuxACallback(AXAuxCallback callback, void* context) {
#if SDK_AUG2010
BOOL enabled = OSDisableInterrupts();
#endif
__AXCallbackAuxA = callback;
__AXContextAuxA = context;
#if SDK_AUG2010
if (callback == NULL) {
memset(&__clearAuxA, TRUE, 3);
}
OSRestoreInterrupts(enabled);
#endif
}
void AXGetAuxACallback(AXAuxCallback* callback, void** context) {
*callback = __AXCallbackAuxA;
*context = __AXContextAuxA;
}
+30
View File
@@ -0,0 +1,30 @@
#include <revolution/ax.h>
#include <revolution/types.h>
static u16 __AXAuxAVolume;
static u16 __AXAuxBVolume;
static u16 __AXAuxCVolume;
u16 AXGetAuxAReturnVolume(void) {
return __AXAuxAVolume;
}
u16 AXGetAuxBReturnVolume(void) {
return __AXAuxBVolume;
}
u16 AXGetAuxCReturnVolume(void) {
return __AXAuxCVolume;
}
void AXSetAuxAReturnVolume(u16 volume) {
__AXAuxAVolume = volume;
}
void AXSetAuxBReturnVolume(u16 volume) {
__AXAuxBVolume = volume;
}
void AXSetAuxCReturnVolume(u16 volume) {
__AXAuxCVolume = volume;
}
+28
View File
@@ -0,0 +1,28 @@
#include <revolution/axfx.h>
#include <revolution/os.h>
#include <revolution/os/OSAlloc.h>
#include <cstdio>
static void* __AXFXAllocFunction(size_t size);
static void __AXFXFreeFunction(void* block);
AXFXAllocHook __AXFXAlloc = __AXFXAllocFunction;
AXFXFreeHook __AXFXFree = __AXFXFreeFunction;
static void* __AXFXAllocFunction(size_t size) {
return OSAllocFromHeap(__OSCurrHeap, size);
}
static void __AXFXFreeFunction(void* block) {
OSFreeToHeap(__OSCurrHeap, block);
}
void AXFXSetHooks(AXFXAllocHook alloc, AXFXFreeHook free) {
__AXFXAlloc = alloc;
__AXFXFree = free;
}
void AXFXGetHooks(AXFXAllocHook* alloc, AXFXFreeHook* free) {
*alloc = __AXFXAlloc;
*free = __AXFXFree;
}
+33
View File
@@ -0,0 +1,33 @@
#include <revolution/axfx.h>
#include <revolution.h>
static void __ParamConvert(AXFX_REVERBHI* fx) {
fx->exp.earlyMode = 5;
fx->exp.preDelayTimeMax = fx->preDelay;
fx->exp.preDelayTime = fx->preDelay;
fx->exp.fusedMode = 0;
fx->exp.fusedTime = fx->time;
fx->exp.coloration = fx->coloration;
fx->exp.damping = fx->damping;
fx->exp.crosstalk = fx->crosstalk;
fx->exp.earlyGain = 0.0f;
fx->exp.fusedGain = 1.0f;
fx->exp.busIn = NULL;
fx->exp.busOut = NULL;
fx->exp.outGain = fx->mix;
fx->exp.sendGain = 0.0f;
}
BOOL AXFXReverbHiInit(AXFX_REVERBHI* fx) {
__ParamConvert(fx);
return AXFXReverbHiExpInit(&fx->exp);
}
BOOL AXFXReverbHiShutdown(AXFX_REVERBHI* fx) {
AXFXReverbHiExpShutdown(&fx->exp);
return TRUE;
}
void AXFXReverbHiCallback(void* chans, void* context) {
AXFXReverbHiExpCallback((AXFX_BUFFERUPDATE*)chans, &((AXFX_REVERBHI*)context)->exp);
}
+418
View File
@@ -0,0 +1,418 @@
#include <revolution/axfx.h>
#include <revolution/mem.h>
#include <cmath>
static u32 __EarlySizeTable[8][3] = {
{157, 479, 829}, {317, 809, 1117}, {479, 941, 1487}, {641, 1259, 1949},
{797, 1667, 2579}, {967, 1901, 2903}, {1123, 2179, 3413}, {1279, 2477, 3889}
};
static f32 __EarlyCoefTable[8][3] = {
{0.4f, -1.0f, 0.3f}, {0.5f, -0.95f, 0.3f}, {0.6f, -0.9f, 0.3f}, {0.75f, -0.85f, 0.3f},
{-0.9f, 0.8f, 0.3f}, {-1.0f, 0.7f, 0.3f}, {-1.0f, 0.7f, 0.3f}, {-1.0f, 0.7f, 0.3f}
};
static u32 __FilterSizeTable[7][8] = {
{1789, 1999, 2333, 433, 149, 47, 73, 67}, {149, 293, 449, 251, 103, 47, 73, 67},
{947, 1361, 1531, 433, 137, 47, 73, 67}, {1279, 1531, 1973, 509, 149, 47, 73, 67},
{1531, 1847, 2297, 563, 179, 47, 73, 67}, {1823, 2357, 2693, 571, 137, 47, 73, 67},
{1823, 2357, 2693, 571, 179, 47, 73, 67}
};
static BOOL __AllocDelayLine(AXFX_REVERBHI_EXP* reverb);
static void __FreeDelayLine(AXFX_REVERBHI_EXP* reverb);
static void __BzeroDelayLines(AXFX_REVERBHI_EXP* reverb);
static BOOL __InitParams(AXFX_REVERBHI_EXP* reverb);
f32 dummy_0() {
return 32000.0f;
}
BOOL AXFXReverbHiExpInit(AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
BOOL result = TRUE;
BOOL mask = OSDisableInterrupts();
reverb->active = 1;
if (reverb->preDelayTimeMax < 0.0f) {
AXFXReverbHiExpShutdown(reverb);
OSRestoreInterrupts(mask);
return FALSE;
}
reverb->earlyMaxLength = __EarlySizeTable[8 - 1][2];
reverb->preDelayMaxLength = (u32)(reverb->preDelayTimeMax * 32000);
for (i = 0; i < 3; i++) {
reverb->combMaxLength[i] = __FilterSizeTable[6][i];
}
for (i = 0; i < 2; i++) {
reverb->allpassMaxLength[i] = __FilterSizeTable[6][3 + i];
}
for (ch = 0; ch < 3; ch++) {
reverb->lastAllpassMaxLength[ch] = __FilterSizeTable[6][5 + ch];
}
result = __AllocDelayLine(reverb);
if (result == FALSE) {
AXFXReverbHiExpShutdown(reverb);
OSRestoreInterrupts(mask);
return FALSE;
}
__BzeroDelayLines(reverb);
result = __InitParams(reverb);
if (result == FALSE) {
AXFXReverbHiExpShutdown(reverb);
OSRestoreInterrupts(mask);
return FALSE;
}
reverb->active &= ~1;
OSRestoreInterrupts(mask);
return TRUE;
}
void AXFXReverbHiExpShutdown(AXFX_REVERBHI_EXP* reverb) {
BOOL mask = OSDisableInterrupts();
reverb->active |= 1;
__FreeDelayLine(reverb);
OSRestoreInterrupts(mask);
}
void AXFXReverbHiExpCallback(AXFX_BUFFERUPDATE* bufferUpdate, AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
u32 samp;
s32* input[3];
f32 data;
f32 output[3];
f32* earlyLine;
f32 earlyOut;
f32* preDelayLine;
f32 preDelayOut;
f32 filterOut;
f32* combLine;
f32 combOutOne;
f32* allpass;
f32 outTmp;
f32 allpassIn;
f32 allpassCoef;
f32 lpfOut;
f32 lpfCoef1;
f32 lpfCoef2;
f32 fusedOut[3];
f32 fusedGain;
f32 crosstalkGain;
f32 crosstalkL;
f32 crosstalkR;
f32 crosstalkS;
s32* inBusData[3];
s32* outBusData[3];
if (reverb->active != 0) {
reverb->active &= ~2;
return;
}
input[0] = bufferUpdate->left;
input[1] = bufferUpdate->right;
input[2] = bufferUpdate->surround;
if (reverb->busIn != NULL) {
inBusData[0] = reverb->busIn->left;
inBusData[1] = reverb->busIn->right;
inBusData[2] = reverb->busIn->surround;
}
if (reverb->busOut != NULL) {
outBusData[0] = reverb->busOut->left;
outBusData[1] = reverb->busOut->right;
outBusData[2] = reverb->busOut->surround;
}
lpfCoef1 = 1.0f - reverb->lpfCoef;
lpfCoef2 = reverb->lpfCoef;
allpassCoef = reverb->allpassCoef;
fusedGain = reverb->fusedGain * 0.6f;
crosstalkGain = reverb->crosstalk * 0.5f;
for (samp = 0; samp < 96; samp++) {
for (ch = 0; ch < 3; ch++) {
if (reverb->busIn != NULL) {
data = (f32)(*(input[ch]) + *(inBusData[ch]++));
} else {
data = (f32)(*input[ch]);
}
earlyLine = reverb->earlyLine[ch];
earlyOut = earlyLine[reverb->earlyPos[0]] * reverb->earlyCoef[0] +
earlyLine[reverb->earlyPos[1]] * reverb->earlyCoef[1] +
earlyLine[reverb->earlyPos[2]] * reverb->earlyCoef[2];
#if SDK_AUG2010
earlyLine[reverb->earlyPos[2]] = data;
#endif
if (reverb->preDelayLength != 0) {
preDelayLine = reverb->preDelayLine[ch];
preDelayOut = preDelayLine[reverb->preDelayPos];
preDelayLine[reverb->preDelayPos] = data;
} else {
preDelayOut = data;
}
filterOut = 0.0f;
for (i = 0; i < 3; i++) {
combLine = reverb->combLine[ch][i];
combOutOne = combLine[reverb->combPos[i]];
combLine[reverb->combPos[i]] = preDelayOut + (combOutOne * reverb->combCoef[i]);
filterOut += combOutOne;
}
for (i = 0; i < 2; i++) {
allpass = reverb->allpassLine[ch][i];
outTmp = allpass[reverb->allpassPos[i]];
allpassIn = filterOut + outTmp * allpassCoef;
allpass[reverb->allpassPos[i]] = allpassIn;
filterOut = outTmp - allpassIn * allpassCoef;
}
lpfOut = lpfCoef1 * filterOut + lpfCoef2 * reverb->lastLpfOut[ch];
reverb->lastLpfOut[ch] = lpfOut;
allpass = reverb->lastAllpassLine[ch];
outTmp = allpass[reverb->lastAllpassPos[ch]];
allpassIn = lpfOut + outTmp * allpassCoef;
allpass[reverb->lastAllpassPos[ch]] = allpassIn;
fusedOut[ch] = outTmp - allpassIn * allpassCoef;
if (++reverb->lastAllpassPos[ch] >= reverb->lastAllpassLength[ch]) {
reverb->lastAllpassPos[ch] = 0;
}
fusedOut[ch] *= fusedGain;
fusedOut[ch] += earlyOut;
}
crosstalkL = fusedOut[1] + fusedOut[2];
crosstalkR = fusedOut[0] + fusedOut[2];
crosstalkS = fusedOut[0] + fusedOut[1];
output[0] = fusedOut[0] + crosstalkL * crosstalkGain;
output[1] = fusedOut[1] + crosstalkR * crosstalkGain;
output[2] = fusedOut[2] + crosstalkS * crosstalkGain;
*(input[0]++) = (s32)(output[0] * reverb->outGain);
*(input[1]++) = (s32)(output[1] * reverb->outGain);
*(input[2]++) = (s32)(output[2] * reverb->outGain);
if (reverb->busOut != NULL) {
*(outBusData[0]++) = (s32)(output[0] * reverb->sendGain);
*(outBusData[1]++) = (s32)(output[1] * reverb->sendGain);
*(outBusData[2]++) = (s32)(output[2] * reverb->sendGain);
}
for (i = 0; i < 3; i++) {
if (++reverb->earlyPos[i] >= reverb->earlyLength) {
reverb->earlyPos[i] = 0;
}
}
if (reverb->preDelayLength != 0) {
if (++reverb->preDelayPos >= reverb->preDelayLength) {
reverb->preDelayPos = 0;
}
}
for (i = 0; i < 3; i++) {
if (++reverb->combPos[i] >= reverb->combLength[i]) {
reverb->combPos[i] = 0;
}
}
for (i = 0; i < 2; i++) {
if (++reverb->allpassPos[i] >= reverb->allpassLength[i]) {
reverb->allpassPos[i] = 0;
}
}
}
}
static BOOL __AllocDelayLine(AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
for (ch = 0; ch < 3; ch++) {
reverb->earlyLine[ch] = (f32*)__AXFXAlloc(sizeof(f32) * reverb->earlyMaxLength);
if (reverb->earlyLine[ch] == NULL)
return FALSE;
if (reverb->preDelayMaxLength != 0) {
reverb->preDelayLine[ch] = (f32*)__AXFXAlloc(sizeof(f32) * reverb->preDelayMaxLength);
if (reverb->preDelayLine[ch] == NULL)
return FALSE;
} else {
reverb->preDelayLine[ch] = NULL;
}
for (i = 0; i < 3; i++) {
reverb->combLine[ch][i] = (f32*)__AXFXAlloc(sizeof(f32) * reverb->combMaxLength[i]);
if (reverb->combLine[ch][i] == NULL)
return FALSE;
}
for (i = 0; i < 2; i++) {
reverb->allpassLine[ch][i] = (f32*)__AXFXAlloc(sizeof(f32) * reverb->allpassMaxLength[i]);
if (reverb->allpassLine[ch][i] == NULL)
return FALSE;
}
reverb->lastAllpassLine[ch] = (f32*)__AXFXAlloc(sizeof(f32) * reverb->lastAllpassMaxLength[ch]);
if (reverb->lastAllpassLine[ch] == NULL)
return FALSE;
}
return TRUE;
}
static void __BzeroDelayLines(AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
for (ch = 0; ch < 3; ch++) {
if (reverb->earlyLine[ch] != NULL) {
memset(reverb->earlyLine[ch], 0, sizeof(f32) * reverb->earlyMaxLength);
}
if (reverb->preDelayLine[ch] != NULL) {
memset(reverb->preDelayLine[ch], 0, sizeof(f32) * reverb->preDelayMaxLength);
}
for (i = 0; i < 3; i++) {
if (reverb->combLine[ch][i] != NULL) {
memset(reverb->combLine[ch][i], 0, sizeof(f32) * reverb->combMaxLength[i]);
}
}
for (i = 0; i < 2; i++) {
if (reverb->allpassLine[ch][i] != NULL) {
memset(reverb->allpassLine[ch][i], 0, sizeof(f32) * reverb->allpassMaxLength[i]);
}
}
if (reverb->lastAllpassLine[ch] != NULL) {
memset(reverb->lastAllpassLine[ch], 0, sizeof(f32) * reverb->lastAllpassMaxLength[ch]);
}
}
}
static void __FreeDelayLine(AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
for (ch = 0; ch < 3; ch++) {
if (reverb->earlyLine[ch] != NULL) {
__AXFXFree(reverb->earlyLine[ch]);
reverb->earlyLine[ch] = NULL;
}
if (reverb->preDelayLine[ch] != NULL) {
__AXFXFree(reverb->preDelayLine[ch]);
reverb->preDelayLine[ch] = NULL;
}
for (i = 0; i < 3; i++) {
if (reverb->combLine[ch][i] != NULL) {
__AXFXFree(reverb->combLine[ch][i]);
reverb->combLine[ch][i] = NULL;
}
}
for (i = 0; i < 2; i++) {
if (reverb->allpassLine[ch][i] != NULL) {
__AXFXFree(reverb->allpassLine[ch][i]);
reverb->allpassLine[ch][i] = NULL;
}
}
if (reverb->lastAllpassLine[ch] != NULL) {
__AXFXFree(reverb->lastAllpassLine[ch]);
reverb->lastAllpassLine[ch] = NULL;
}
}
}
f32 dummy_1() {
return -3.0f;
}
static BOOL __InitParams(AXFX_REVERBHI_EXP* reverb) {
u32 ch, i;
if (reverb->earlyMode >= 8)
return FALSE;
if (reverb->preDelayTime < 0.0f || reverb->preDelayTime > reverb->preDelayTimeMax)
return FALSE;
if (reverb->fusedMode >= 6)
return FALSE;
if (reverb->fusedTime < 0.0f)
return FALSE;
if (reverb->coloration < 0.0f || reverb->coloration > 1.0f)
return FALSE;
if (reverb->damping < 0.0f || reverb->damping > 1.0f)
return FALSE;
if (reverb->crosstalk < 0.0f || reverb->crosstalk > 1.0f)
return FALSE;
if (reverb->earlyGain < 0.0f || reverb->earlyGain > 1.0f)
return FALSE;
if (reverb->fusedGain < 0.0f || reverb->fusedGain > 1.0f)
return FALSE;
if (reverb->outGain < 0.0f || reverb->outGain > 1.0f)
return FALSE;
if (reverb->sendGain < 0.0f || reverb->sendGain > 1.0f)
return FALSE;
reverb->earlyLength = __EarlySizeTable[reverb->earlyMode][2];
for (i = 0; i < 3; i++) {
reverb->earlyPos[i] = reverb->earlyLength - __EarlySizeTable[reverb->earlyMode][i];
reverb->earlyCoef[i] = __EarlyCoefTable[reverb->earlyMode][i] * reverb->earlyGain * 0.6f;
}
reverb->preDelayPos = 0;
reverb->preDelayLength = (u32)(reverb->preDelayTime * (f32)32000);
for (i = 0; i < 3; i++) {
reverb->combPos[i] = 0;
reverb->combLength[i] = __FilterSizeTable[reverb->fusedMode][i];
reverb->combCoef[i] = pow(10.0f, (-3.0f * (f32)(reverb->combLength[i]) / (f32)(reverb->fusedTime * 32000)));
}
for (i = 0; i < 2; i++) {
reverb->allpassPos[i] = 0;
reverb->allpassLength[i] = __FilterSizeTable[reverb->fusedMode][3 + i];
}
for (ch = 0; ch < 3; ch++) {
reverb->lastAllpassPos[ch] = 0;
reverb->lastAllpassLength[ch] = __FilterSizeTable[reverb->fusedMode][5 + ch];
}
reverb->allpassCoef = reverb->coloration;
reverb->lpfCoef = 1.0f - reverb->damping;
if (reverb->lpfCoef > 0.95f)
reverb->lpfCoef = 0.95f;
for (ch = 0; ch < 3; ch++) {
reverb->lastLpfOut[ch] = 0.0f;
}
return TRUE;
}
+2 -2
View File
@@ -260,8 +260,8 @@ namespace homebutton {
/* 0x5D0 */ nw4hbm::snd::SoundHeap* mpSoundHeap;
/* 0x5D4 */ nw4hbm::snd::SoundHandle* mpSoundHandle;
/* 0x5D8 */ u16 mAppVolume[3];
/* 0x5E0 */ AXFXAllocFunc mAxFxAlloc;
/* 0x5E4 */ AXFXFreeFunc mAxFxFree;
/* 0x5E0 */ AXFXAllocHook mAxFxAlloc;
/* 0x5E4 */ AXFXFreeHook mAxFxFree;
/* 0x5E8 */ AXFX_REVERBHI mAxFxReverb;
/* 0x748 */ AXAuxCallback mAuxCallback;
/* 0x74C */ void* mpAuxContext;
+2
View File
@@ -23,10 +23,12 @@ void IPCInit(void) {
Initialized = TRUE;
}
#if SDK_AUG2010
void IPCReInit(void) {
Initialized = FALSE;
IPCInit();
}
#endif
u32 IPCReadReg(u32 regIdx) {
u32 reg = __IPCRegs[regIdx];
+124 -14
View File
@@ -1,17 +1,40 @@
#include <revolution.h>
#include <cstring>
static u32 IpcReqPtrArray[96] = {0};
static u32 IpcReqArray[0x300] = {0};
static OSTime IpcStartTimeArray[96];
static u8 IpcHandlePathBuf[0x1800];
static u8 IpcOpenPathBuf[0x1200];
#if SDK_AUG2010
#define IPC_REQ_MAX 0x60
#define IPC_PATH_MAX 0x30
#else
#define IPC_REQ_MAX 0x20
#endif
#if SDK_AUG2010
// either release or debug config does something weird to swap the order of these in .bss
#if VERSION == VERSION_SHIELD_DEBUG
static IOSResourceRequest* IpcReqPtrArray[IPC_REQ_MAX] = {0};
static IOSResourceRequest IpcReqArray[IPC_REQ_MAX] = {0};
#else
static IOSResourceRequest IpcReqArray[IPC_REQ_MAX] = {0};
static IOSResourceRequest* IpcReqPtrArray[IPC_REQ_MAX] = {0};
#endif
static OSTime IpcStartTimeArray[IPC_REQ_MAX];
static char IpcHandlePathBuf[0x80][0x30];
static char IpcOpenPathBuf[IPC_REQ_MAX][0x30];
#else
static s32 IpcFdArray[IPC_REQ_MAX] = {0};
static u32 IpcReqPtrArray[IPC_REQ_MAX] = {0};
#endif
static u32 IpcNumPendingReqs = 0;
static u32 IpcNumUnIssuedReqs = 0;
static void AddReqInfo(void* req);
static void DelReqInfo(void* req);
#if SDK_AUG2010
static void AddReqInfo(IOSResourceRequest* req);
static void DelReqInfo(IOSResourceRequest* req);
#else
static void AddReqInfo(IOSResourceRequest* req, s32 fd);
static void DelReqInfo(IOSResourceRequest* req, s32 fd);
#endif
void IPCiProfInit(void) {
u32 i;
@@ -19,20 +42,31 @@ void IPCiProfInit(void) {
IpcNumPendingReqs = 0;
IpcNumUnIssuedReqs = 0;
for (i = 0; i < 96; ++i) {
for (i = 0; i < IPC_REQ_MAX; ++i) {
#if SDK_AUG2010
IpcReqPtrArray[i] = 0;
IpcStartTimeArray[i] = 0;
#else
IpcReqPtrArray[i] = 0;
IpcFdArray[i] = -1;
#endif
}
#if SDK_AUG2010
memset(IpcHandlePathBuf, 0, sizeof(IpcHandlePathBuf));
memset(IpcOpenPathBuf, 0, sizeof(IpcOpenPathBuf));
memset(IpcReqArray, 0, sizeof(IpcReqArray));
#endif
}
void IPCiProfQueueReq(void* req, s32 handle) {
++IpcNumPendingReqs;
++IpcNumUnIssuedReqs;
AddReqInfo(req);
#if SDK_AUG2010
AddReqInfo((IOSResourceRequest*)req);
#else
AddReqInfo((IOSResourceRequest*)req, handle);
#endif
}
void IPCiProfAck(void) {
@@ -41,13 +75,89 @@ void IPCiProfAck(void) {
void IPCiProfReply(void* req, s32 handle) {
--IpcNumPendingReqs;
DelReqInfo(req);
#if SDK_AUG2010
DelReqInfo((IOSResourceRequest*)req);
#else
DelReqInfo((IOSResourceRequest*)req, handle);
#endif
}
static void AddReqInfo(void* ptr) {
// NONMATCHING
#if SDK_AUG2010
static void AddReqInfo(IOSResourceRequest* req) {
u32 i;
for (i = 0; i < IPC_REQ_MAX; i++) {
if (!IpcReqPtrArray[i]) {
BOOL irqEnabled = OSDisableInterrupts();
IpcReqPtrArray[i] = req;
IpcReqArray[i] = *req;
IpcStartTimeArray[i] = OSGetTime();
if (IpcReqArray[i].cmd == 1) {
const char* path_p_virt = (const char*)OSPhysicalToCached((u32)IpcReqArray[i].args.open.path);
strncpy(IpcOpenPathBuf[i], path_p_virt,
IPC_PATH_MAX - 1);
IpcOpenPathBuf[i][IPC_PATH_MAX - 1] = '\0';
IpcReqArray[i].args.open.path = (u8*)IpcOpenPathBuf[i];
}
OSRestoreInterrupts(irqEnabled);
break;
}
}
}
static void DelReqInfo(void* ptr) {
// NONMATCHING
static void DelReqInfo(IOSResourceRequest* req) {
u32 i;
for (i = 0; i < IPC_REQ_MAX; i++) {
if (req == IpcReqPtrArray[i] && req->handle == IpcReqArray[i].cmd) {
BOOL irqEnabled = OSDisableInterrupts();
if (IpcReqArray[i].cmd == 1) {
if (req->status >= 0) {
strncpy(IpcHandlePathBuf[req->status],
(const char*)IpcReqArray[i].args.open.path, IPC_PATH_MAX - 1);
IpcHandlePathBuf[req->status][IPC_PATH_MAX - 1] = '\0';
memset(&IpcOpenPathBuf[i], 0, IPC_PATH_MAX);
}
}
if (IpcReqArray[i].cmd == 2) {
memset(&IpcHandlePathBuf[IpcReqArray[i].handle], 0, IPC_PATH_MAX);
}
IpcReqPtrArray[i] = NULL;
memset(&IpcReqArray[i], 0, sizeof(IOSResourceRequest));
IpcStartTimeArray[i] = 0;
OSRestoreInterrupts(irqEnabled);
break;
}
}
}
#else
static void AddReqInfo(IOSResourceRequest* ptr, s32 fd) {
u32 i;
for (i = 0; i < 32; ++i) {
if (IpcReqPtrArray[i] == 0 && IpcFdArray[i] == -1) {
IpcReqPtrArray[i] = (u32)ptr;
IpcFdArray[i] = fd;
break;
}
}
}
static void DelReqInfo(IOSResourceRequest* ptr, s32 fd) {
u32 i;
for (i = 0; i < 32; ++i) {
if (IpcReqPtrArray[i] == (u32)ptr && IpcFdArray[i] == fd) {
IpcReqPtrArray[i] = 0;
IpcFdArray[i] = -1;
break;
}
}
}
#endif
+39 -6
View File
@@ -4,6 +4,14 @@
#include <revolution/ipc.h>
#include <cstring>
#if SDK_AUG2010
#define RESPONSE_REQ_BUF_LEN 0x30
#define IPC_BUF_CNT 0x40
#else
#define RESPONSE_REQ_BUF_LEN 0x10
#define IPC_BUF_CNT 0x10
#endif
/* macro for matching __ipcQueueRequest */
#define diff(a, b) \
((a) < (b)) ? ((u32)0xffffffff - (b) + (a) + 1) : ((a) - (b))
@@ -23,9 +31,11 @@ typedef struct IOSRpcRequest {
} IOSRpcRequest;
static IOSRpcRequest* __relnchRpc = 0;
#if SDK_AUG2010
static IOSRpcRequest* __relnchRpcSave = 0;
#endif
#define ROUNDUP(sz) (((u32)(sz) + 31) & ~(u32)(31))
#define ROUNDUP(sz) (((u32)(sz) + (IPC_BUF_CNT / 2 - 1)) & ~(u32)(IPC_BUF_CNT / 2 - 1))
static u8 __rpcBuf[ROUNDUP(sizeof(IOSRpcRequest))] ATTRIBUTE_ALIGN(32);
@@ -34,7 +44,7 @@ static struct {
u32 wcount;
u32 rptr;
u32 wptr;
IOSResourceRequest* buf[48];
IOSResourceRequest* buf[RESPONSE_REQ_BUF_LEN];
} __responses;
static OSAlarm __timeout_alarm;
@@ -93,6 +103,10 @@ static void __ipcSendRequest(void) {
}
if (rpc->relaunch_flag) {
#if !SDK_AUG2010
__relnchFl = 1;
__relnchRpc = rpc;
#endif
__mailboxAck--;
}
@@ -149,7 +163,12 @@ void IpcReplyHandler(__OSInterrupt interrupt, OSContext* context) {
DCInvalidateRange(v->vector[i].base, v->vector[i].length);
}
if (__relnchFl && __relnchRpcSave == rep) {
#if SDK_AUG2010
if (__relnchFl && __relnchRpcSave == rep)
#else
if (__relnchFl && __relnchRpc == rep)
#endif
{
__relnchFl = 0;
if (__mailboxAck < 1) {
@@ -229,7 +248,7 @@ IOSError IPCCltInit(void) {
IPCInit();
i = ROUNDUP(64 * (ROUNDUP(sizeof(IOSRpcRequest)) + 64));
i = ROUNDUP(IPC_BUF_CNT * (ROUNDUP(sizeof(IOSRpcRequest)) + 64));
bufferLo = IPCGetBufferLo();
if ((void*)((u8*)bufferLo + i) > IPCGetBufferHi()) {
@@ -245,18 +264,21 @@ IOSError IPCCltInit(void) {
IPCWriteReg(1, (1 << 5 | 1<< 4 | 1 << 3));
IPCiProfInit();
#if SDK_AUG2010
OSCreateAlarm(&__timeout_alarm);
#endif
out:
return ret;
}
#if SDK_AUG2010
IOSError IPCCltReInit(void) {
u32 i;
IOSError ret = 0;
void* bufferLo;
i = ROUNDUP(64 * ROUNDUP(sizeof(IOSRpcRequest)));
i = ROUNDUP(IPC_BUF_CNT * ROUNDUP(sizeof(IOSRpcRequest)));
bufferLo = IPCGetBufferLo();
if ((void*)((u8*)bufferLo + i) > IPCGetBufferHi()) {
@@ -270,6 +292,7 @@ IOSError IPCCltReInit(void) {
out:
return ret;
}
#endif
static IOSError __ios_Ipc1(IOSFd fd, u32 cmd, IOSIpcCb cb, void* cbArg, IOSRpcRequest** rpc) {
IOSError ret = 0;
@@ -773,6 +796,7 @@ IOSError IOS_IoctlvReboot(IOSFd fd, s32 cmd, u32 readCount, u32 writeCount, IOSI
u32 inten;
IOSResourceRequest* req;
#if SDK_AUG2010
inten = OSDisableInterrupts();
if (__relnchFl) {
@@ -783,6 +807,7 @@ IOSError IOS_IoctlvReboot(IOSFd fd, s32 cmd, u32 readCount, u32 writeCount, IOSI
__relnchFl = 1;
OSRestoreInterrupts(inten);
#endif
ret = __ios_Ipc1(fd, 7, 0, 0, &rpc);
@@ -790,15 +815,18 @@ IOSError IOS_IoctlvReboot(IOSFd fd, s32 cmd, u32 readCount, u32 writeCount, IOSI
goto err;
}
#if SDK_AUG2010
__relnchRpcSave = rpc;
#endif
rpc->relaunch_flag = 1;
ret = __ios_Ioctlv(rpc, cmd, readCount, writeCount, vect);
if (ret != 0) {
goto err;
}
#if SDK_AUG2010
memcpy(&__rpcBuf, rpc, sizeof(IOSRpcRequest));
__relnchRpc = (IOSRpcRequest*)&__rpcBuf;
req = &rpc->request;
@@ -821,14 +849,19 @@ IOSError IOS_IoctlvReboot(IOSFd fd, s32 cmd, u32 readCount, u32 writeCount, IOSI
OSSleepThread(&__relnchRpc->thread_queue);
OSRestoreInterrupts(inten);
ret = (&__relnchRpc->request)->status;
#else
ret = __ios_Ipc2(rpc, NULL);
#endif
err:
#if SDK_AUG2010
__relnchFl = 0;
__relnchRpcSave = NULL;
if (rpc && (ret != 0)) {
ipcFree(rpc);
}
#endif
finish:
return ret;
+31
View File
@@ -0,0 +1,31 @@
#include <revolution/mem/allocator.h>
#include <revolution/mem/expHeap.h>
static void* AllocatorAllocForExpHeap_(MEMAllocator *pAllocator, u32 size) {
return MEMAllocFromExpHeapEx(pAllocator->pHeap, size, pAllocator->heapParam1);
}
static void AllocatorFreeForExpHeap_(MEMAllocator *pAllocator, void *pBlock) {
MEMFreeToExpHeap(pAllocator->pHeap, pBlock);
}
void* MEMAllocFromAllocator(MEMAllocator *pAllocator, u32 size) {
return (*pAllocator->pFunc->pfAlloc)(pAllocator, size);
}
void MEMFreeToAllocator(MEMAllocator *pAllocator, void *pBlock) {
(*pAllocator->pFunc->pfFree)(pAllocator, pBlock);
}
void MEMInitAllocatorForExpHeap(MEMAllocator *pAllocator, MEMHeapHandle handle, int align) {
static const MEMAllocatorFunc sAllocatorFunc =
{
AllocatorAllocForExpHeap_,
AllocatorFreeForExpHeap_,
};
pAllocator->pFunc = &sAllocatorFunc;
pAllocator->pHeap = handle;
pAllocator->heapParam1 = align;
pAllocator->heapParam2 = 0;
}
+380
View File
@@ -0,0 +1,380 @@
#include <revolution/mem/expHeap.h>
#include <revolution/mem/heapCommon.h>
#define FillFreeMemory(pHeapHd, address, size) ((void)0)
#define FillNoUseMemory(pHeapHd, address, size) ((void)0)
#define RoundUp(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment) - 1))
#define RoundUpPtr(ptr, alignment) ((void*)RoundUp(GetUIntPtr(ptr), (alignment)))
#define RoundDown(value, alignment) ((value) & ~((alignment) - 1))
#define RoundDownPtr(ptr, alignment) ((void*)RoundDown(GetUIntPtr(ptr), (alignment)))
typedef struct MemRegion MemRegion;
struct MemRegion {
void* start;
void* end;
};
static inline void* GetMemPtrForMBlock_(MEMiExpHeapMBlockHead* pMBlkHd) {
return AddU32ToPtr(pMBlkHd, sizeof(MEMiExpHeapMBlockHead));
}
static inline void* GetMBlockEndAddr_(MEMiExpHeapMBlockHead* pMBHead) {
return AddU32ToPtr(GetMemPtrForMBlock_(pMBHead), pMBHead->blockSize);
}
static inline u16 GetAllocMode_(MEMiExpHeapHead* pEHHead) {
return pEHHead->feature.fields.allocMode;
}
static MEMiExpHeapMBlockHead* InitMBlock_(MemRegion* pRegion, u16 signature) {
MEMiExpHeapMBlockHead* block = (MEMiExpHeapMBlockHead*)pRegion->start;
block->signature = signature;
block->attribute.val = 0;
block->blockSize = GetOffsetFromPtr(GetMemPtrForMBlock_(block), pRegion->end);
block->prev = NULL;
block->next = NULL;
return block;
}
static inline void SetAllocDirForMBlock_(MEMiExpHeapMBlockHead* pMBHead, u16 mode) {
pMBHead->attribute.fields.allocDir = mode;
}
static inline u16 GetAlignmentForMBlock_(const MEMiExpHeapMBlockHead* pMBlkHd) {
return pMBlkHd->attribute.fields.alignment;
}
static inline void SetAlignmentForMBlock_(MEMiExpHeapMBlockHead* pMBlkHd, u16 alignment) {
pMBlkHd->attribute.fields.alignment = alignment;
}
static inline void SetGroupIDForMBlock_(MEMiExpHeapMBlockHead* pMBHead, u16 id) {
pMBHead->attribute.fields.groupID = (u8)id;
}
static void GetRegionOfMBlock_(MemRegion* region, MEMiExpHeapMBlockHead* block) {
region->start = SubU32ToPtr(block, GetAlignmentForMBlock_(block));
region->end = GetMBlockEndAddr_(block);
}
static inline MEMiHeapHead* GetHeapHeadPtrFromExpHeapHead_(MEMiExpHeapHead* pEHHead) {
return (MEMiHeapHead*)SubU32ToPtr(pEHHead, sizeof(MEMiHeapHead));
}
static MEMiExpHeapMBlockHead* InsertMBlock_(MEMiExpMBlockList* list, MEMiExpHeapMBlockHead* target, MEMiExpHeapMBlockHead* prev) {
MEMiExpHeapMBlockHead* next;
target->prev = prev;
if (prev) {
next = prev->next;
prev->next = target;
} else {
next = list->head;
list->head = target;
}
target->next = next;
if (next) {
next->prev = target;
} else {
list->tail = target;
}
return target;
}
static inline void AppendMBlock_(MEMiExpMBlockList* list, MEMiExpHeapMBlockHead* block) {
(void)InsertMBlock_(list, block, list->tail);
}
static inline MEMiExpHeapHead* GetExpHeapHeadPtrFromHeapHead_(MEMiHeapHead* pHHead) {
return (MEMiExpHeapHead*)AddU32ToPtr(pHHead, sizeof(MEMiHeapHead));
}
static MEMiExpHeapMBlockHead* RemoveMBlock_(MEMiExpMBlockList* list, MEMiExpHeapMBlockHead* block) {
MEMiExpHeapMBlockHead* const prev = block->prev;
MEMiExpHeapMBlockHead* const next = block->next;
if (prev) {
prev->next = next;
} else {
list->head = next;
}
if (next) {
next->prev = prev;
} else {
list->tail = prev;
}
return prev;
}
static inline MEMiExpHeapMBlockHead* InitFreeMBlock_(MemRegion* pRegion) {
return InitMBlock_(pRegion, 'FR');
}
static inline void SetAllocMode_(MEMiExpHeapHead* pEHHead, u16 mode) {
pEHHead->feature.fields.allocMode = mode;
}
static MEMiHeapHead* InitExpHeap_(void* startAddress, void* endAddress, u16 optFlag) {
MEMiHeapHead* pHeapHd = (MEMiHeapHead*)startAddress;
MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
MEMiInitHeapHead(pHeapHd, 'EXPH', AddU32ToPtr(pExpHeapHd, sizeof(MEMiExpHeapHead)), endAddress, optFlag);
pExpHeapHd->groupID = 0;
pExpHeapHd->feature.val = 0;
SetAllocMode_(pExpHeapHd, 0);
{
MEMiExpHeapMBlockHead* pMBHead;
MemRegion region;
region.start = pHeapHd->heapStart;
region.end = pHeapHd->heapEnd;
pMBHead = InitFreeMBlock_(&region);
pExpHeapHd->mbFreeList.head = pMBHead;
pExpHeapHd->mbFreeList.tail = pMBHead;
pExpHeapHd->mbUsedList.head = NULL;
pExpHeapHd->mbUsedList.tail = NULL;
return pHeapHd;
}
}
static void* AllocUsedBlockFromFreeBlock_(MEMiExpHeapHead* pEHHead, MEMiExpHeapMBlockHead* pMBHeadFree, void* mblock, u32 size, u16 direction) {
MemRegion freeRgnT;
MemRegion freeRgnB;
MEMiExpHeapMBlockHead* pMBHeadFreePrev;
GetRegionOfMBlock_(&freeRgnT, pMBHeadFree);
freeRgnB.end = freeRgnT.end;
freeRgnB.start = AddU32ToPtr(mblock, size);
freeRgnT.end = SubU32ToPtr(mblock, sizeof(MEMiExpHeapMBlockHead));
pMBHeadFreePrev = RemoveMBlock_(&pEHHead->mbFreeList, pMBHeadFree);
if ((GetOffsetFromPtr(freeRgnT.start, freeRgnT.end) < sizeof(MEMiExpHeapMBlockHead) + 4)
#if SDK_AUG2010
|| (direction == 0 && !pEHHead->feature.fields.useMarginOfAlign)
#endif
) {
freeRgnT.end = freeRgnT.start;
} else {
pMBHeadFreePrev = InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnT), pMBHeadFreePrev);
}
if ((GetOffsetFromPtr(freeRgnB.start, freeRgnB.end) < sizeof(MEMiExpHeapMBlockHead) + 4)
#if SDK_AUG2010
|| (direction == 1 && !pEHHead->feature.fields.useMarginOfAlign)
#endif
) {
freeRgnB.start = freeRgnB.end;
} else {
(void)InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&freeRgnB), pMBHeadFreePrev);
}
FillAllocMemory(GetHeapHeadPtrFromExpHeapHead_(pEHHead), freeRgnT.end, GetOffsetFromPtr(freeRgnT.end, freeRgnB.start));
{
MEMiExpHeapMBlockHead* pMBHeadNewUsed;
MemRegion region;
region.start = SubU32ToPtr(mblock, sizeof(MEMiExpHeapMBlockHead));
region.end = freeRgnB.start;
pMBHeadNewUsed = InitMBlock_(&region, 'UD');
SetAllocDirForMBlock_(pMBHeadNewUsed, direction);
SetAlignmentForMBlock_(pMBHeadNewUsed, (u16)GetOffsetFromPtr(freeRgnT.end, pMBHeadNewUsed));
SetGroupIDForMBlock_(pMBHeadNewUsed, pEHHead->groupID);
AppendMBlock_(&pEHHead->mbUsedList, pMBHeadNewUsed);
}
return mblock;
}
static void* AllocFromHead_(MEMiHeapHead* pHeapHd, u32 size, int alignment) {
MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == 0;
MEMiExpHeapMBlockHead* pMBlkHd = NULL;
MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
u32 foundSize = 0xffffffff;
void* foundMBlock = NULL;
for (pMBlkHd = pExpHeapHd->mbFreeList.head; pMBlkHd; pMBlkHd = pMBlkHd->next) {
void* const mblock = GetMemPtrForMBlock_(pMBlkHd);
void* const reqMBlock = RoundUpPtr(mblock, alignment);
const u32 offset = GetOffsetFromPtr(mblock, reqMBlock);
if (pMBlkHd->blockSize >= size + offset && foundSize > pMBlkHd->blockSize) {
pMBlkHdFound = pMBlkHd;
foundSize = pMBlkHd->blockSize;
foundMBlock = reqMBlock;
if (bAllocFirst || foundSize == size) {
break;
}
}
}
if (!pMBlkHdFound) {
return NULL;
}
return AllocUsedBlockFromFreeBlock_(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 0);
}
static void* AllocFromTail_(MEMiHeapHead* pHeapHd, u32 size, int alignment) {
MEMiExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead_(pHeapHd);
const BOOL bAllocFirst = GetAllocMode_(pExpHeapHd) == 0;
MEMiExpHeapMBlockHead* pMBlkHd = NULL;
MEMiExpHeapMBlockHead* pMBlkHdFound = NULL;
u32 foundSize = 0xffffffff;
void* foundMBlock = NULL;
for (pMBlkHd = pExpHeapHd->mbFreeList.tail; pMBlkHd; pMBlkHd = pMBlkHd->prev) {
void* const mblock = GetMemPtrForMBlock_(pMBlkHd);
void* const mblockEnd = AddU32ToPtr(mblock, pMBlkHd->blockSize);
void* const reqMBlock = RoundDownPtr(SubU32ToPtr(mblockEnd, size), alignment);
if (ComparePtr(reqMBlock, mblock) >= 0 && foundSize > pMBlkHd->blockSize) {
pMBlkHdFound = pMBlkHd;
foundSize = pMBlkHd->blockSize;
foundMBlock = reqMBlock;
if (bAllocFirst || foundSize == size) {
break;
}
}
}
if (!pMBlkHdFound) {
return NULL;
}
return AllocUsedBlockFromFreeBlock_(pExpHeapHd, pMBlkHdFound, foundMBlock, size, 1);
}
static BOOL RecycleRegion_(MEMiExpHeapHead* pEHHead, const MemRegion* pRegion) {
MEMiExpHeapMBlockHead* pBlkPrFree = NULL;
MemRegion freeRgn = *pRegion;
{
MEMiExpHeapMBlockHead* pBlk;
for (pBlk = pEHHead->mbFreeList.head; pBlk; pBlk = pBlk->next) {
if (pBlk < pRegion->start) {
pBlkPrFree = pBlk;
continue;
}
if (pBlk == pRegion->end) {
freeRgn.end = GetMBlockEndAddr_(pBlk);
(void)RemoveMBlock_(&pEHHead->mbFreeList, pBlk);
FillNoUseMemory(GetHeapHeadPtrFromExpHeapHead_(pEHHead), pBlk, sizeof(MEMiExpHeapMBlockHead));
}
break;
}
}
if (pBlkPrFree && GetMBlockEndAddr_(pBlkPrFree) == pRegion->start) {
freeRgn.start = pBlkPrFree;
pBlkPrFree = RemoveMBlock_(&pEHHead->mbFreeList, pBlkPrFree);
}
if (GetOffsetFromPtr(freeRgn.start, freeRgn.end) < sizeof(MEMiExpHeapMBlockHead)) {
return FALSE;
}
FillFreeMemory(GetHeapHeadPtrFromExpHeapHead_(pEHHead), pRegion->start, GetOffsetFromPtr(pRegion->start, pRegion->end));
(void)InsertMBlock_(&pEHHead->mbFreeList, InitFreeMBlock_(&freeRgn), pBlkPrFree);
return TRUE;
}
MEMHeapHandle MEMCreateExpHeapEx(void* startAddress, u32 size, u16 optFlag) {
void* endAddress;
endAddress = RoundDownPtr(AddU32ToPtr(startAddress, size), 4);
startAddress = RoundUpPtr(startAddress, 4);
if (GetUIntPtr(startAddress) > GetUIntPtr(endAddress) ||
GetOffsetFromPtr(startAddress, endAddress) < sizeof(MEMiHeapHead) + sizeof(MEMiExpHeapHead) + sizeof(MEMiExpHeapMBlockHead) + 4) {
return 0;
}
{
MEMiHeapHead* pHeapHd = InitExpHeap_(startAddress, endAddress, optFlag);
return pHeapHd;
}
}
void* MEMAllocFromExpHeapEx(MEMHeapHandle heap, u32 size, int alignment) {
void* memory = NULL;
if (size == 0) {
size = 1;
}
size = RoundUp(size, 4);
LockHeap(heap);
if (alignment >= 0) {
memory = AllocFromHead_(heap, size, alignment);
} else {
memory = AllocFromTail_(heap, size, -alignment);
}
UnlockHeap(heap);
return memory;
}
static inline MEMiExpHeapMBlockHead* GetMBlockHeadPtr_(void* memBlock) {
return (MEMiExpHeapMBlockHead*)SubU32ToPtr(memBlock, sizeof(MEMiExpHeapMBlockHead));
}
static inline MEMiExpHeapHead* GetExpHeapHeadPtrFromHandle_(MEMHeapHandle heap) {
return (MEMiExpHeapHead*)GetExpHeapHeadPtrFromHeapHead_(heap);
}
void MEMFreeToExpHeap(MEMHeapHandle heap, void* memBlock) {
MEMiHeapHead* pHeapHd;
MEMiExpHeapHead* pExpHeapHd;
MEMiExpHeapMBlockHead* pMBHead;
MemRegion region;
if (memBlock == NULL) {
return;
}
#if SDK_AUG2010
LockHeap(heap);
#endif
pHeapHd = heap;
pExpHeapHd = GetExpHeapHeadPtrFromHandle_(pHeapHd);
pMBHead = GetMBlockHeadPtr_(memBlock);
#if !SDK_AUG2010
LockHeap(heap);
#endif
GetRegionOfMBlock_(&region, pMBHead);
(void)RemoveMBlock_(&pExpHeapHd->mbUsedList, pMBHead);
(void)RecycleRegion_(pExpHeapHd, &region);
UnlockHeap(heap);
}
+57
View File
@@ -0,0 +1,57 @@
#include <revolution/mem/heapCommon.h>
#include <revolution/mem/list.h>
static MEMList sRootList;
static BOOL sRootListInitialized = FALSE;
static OSMutex sRootMutex;
static MEMiHeapHead* FindContainHeap_(MEMList* pList, const void* memBlock) {
MEMiHeapHead* pHeapHd = NULL;
while (NULL != (pHeapHd = (MEMiHeapHead*)MEMGetNextListObject(pList, pHeapHd))) {
if (GetUIntPtr(pHeapHd->heapStart) <= GetUIntPtr(memBlock) && GetUIntPtr(memBlock) < GetUIntPtr(pHeapHd->heapEnd)) {
MEMiHeapHead* pChildHeapHd = FindContainHeap_(&pHeapHd->childList, memBlock);
if (pChildHeapHd) {
return pChildHeapHd;
}
return pHeapHd;
}
}
return NULL;
}
static MEMList* FindListContainHeap_(const MEMiHeapHead* pHeapHd) {
MEMList* pList = &sRootList;
MEMiHeapHead* pContainHeap = FindContainHeap_(&sRootList, pHeapHd);
if (pContainHeap) {
pList = &pContainHeap->childList;
}
return pList;
}
#define FillNoUseMemory(pHeapHd, address, size) ((void)0)
void MEMiInitHeapHead(MEMiHeapHead* pHeapHd, u32 signature, void* heapStart, void* heapEnd, u16 optFlag) {
pHeapHd->signature = signature;
pHeapHd->heapStart = heapStart;
pHeapHd->heapEnd = heapEnd;
pHeapHd->attribute.val = 0;
SetOptForHeap(pHeapHd, optFlag);
FillNoUseMemory(pHeapHd, heapStart, GetOffsetFromPtr(heapStart, heapEnd));
MEM_INIT_LIST(&pHeapHd->childList, MEMiHeapHead, link);
if (!sRootListInitialized) {
MEM_INIT_LIST(&sRootList, MEMiHeapHead, link);
OSInitMutex(&sRootMutex);
sRootListInitialized = TRUE;
}
OSInitMutex(&pHeapHd->mutex);
OSLockMutex(&sRootMutex);
MEMAppendListObject(FindListContainHeap_(pHeapHd), pHeapHd);
OSUnlockMutex(&sRootMutex);
}
+41
View File
@@ -0,0 +1,41 @@
#include <revolution/mem/list.h>
// I've tried inlines but only a macro seems to work
#define GetLink(parent_list, obj) ((MEMLink*)(((u32)(obj))+(parent_list)->offs))
void MEMInitList(MEMList *pList, u16 offs) {
pList->head = NULL;
pList->tail = NULL;
pList->num = 0;
pList->offs = offs;
}
void MEMAppendListObject(MEMList *pList, void *pObj) {
MEMLink* link;
if (pList->head == NULL) {
link = GetLink(pList, pObj);
link->next = NULL;
link->prev = NULL;
pList->head = pObj;
pList->tail = pObj;
pList->num++;
}
else {
link = GetLink(pList, pObj);
link->prev = pList->tail;
link->next = NULL;
GetLink(pList, pList->tail)->next = pObj;
pList->tail = pObj;
pList->num++;
}
}
void* MEMGetNextListObject(MEMList *pList, void *pObj) {
if (pObj == NULL) {
return pList->head;
}
return GetLink(pList, pObj)->next;
}
+2
View File
@@ -515,8 +515,10 @@ void __OSLaunchNextFirmware(void) {
}
__OSInitIPCBuffer();
#if SDK_AUG2010
IPCReInit();
IPCCltReInit();
#endif
DVDLowInit();
DVDLowIntType = 0;
+1 -1
View File
@@ -7,7 +7,7 @@
#include "__os.h"
OSAlarm __OSExpireAlarm;
OSAlarm __OSExpireAlarm ATTRIBUTE_ALIGN(32);
OSTime __OSExpireTime;
OSPlayTimeCallbackFunc __OSExpireCallback;
BOOL __OSExpireSetExpiredFlag;
+45 -13
View File
@@ -5,6 +5,7 @@
#include <cstring>
#include "__si.h"
#include "revolution/vi/__vi.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -14,11 +15,11 @@
#if DEBUG
#define BUILD_TIME "17:27:55"
#else
#define BUILD_TIME "17:33:06"
#define BUILD_TIME "17:33:17"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#define BUILD_DATE "Sep 7 2006"
#define BUILD_TIME "07:20:50"
#endif
#ifdef SDK_AUG2010
@@ -143,7 +144,7 @@ static void DoReset() {
ASSERTLINE(589, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN);
chanBit = (PAD_CHAN0_BIT >> ResettingChan);
ResettingBits &= ~chanBit;
memset(&Origin[ResettingChan], 0, sizeof(PADStatus));
SIGetTypeAsync(ResettingChan, PADTypeAndStatusCallback);
}
@@ -221,7 +222,7 @@ static void PADProbeCallback(s32 chan, u32 error, OSContext* context) {
ASSERTLINE(740, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN);
ASSERTLINE(741, chan == ResettingChan);
ASSERTLINE(743, (Type[chan] & SI_WIRELESS_CONT_MASK) == SI_WIRELESS_CONT && !(Type[chan] & SI_WIRELESS_LITE));
if (!(error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)))
{
PADEnable(ResettingChan);
@@ -381,7 +382,7 @@ BOOL PADInit() {
if (Initialized) {
return 1;
}
OSRegisterVersion(__PADVersion);
if (__PADSpec)
@@ -394,7 +395,7 @@ BOOL PADInit() {
__OSWirelessPadFixMode
= (u16)((((time)&0xffff) + ((time >> 16) & 0xffff) + ((time >> 32) & 0xffff) + ((time >> 48) & 0xffff))
& 0x3fffu);
RecalibrateBits = PAD_CHAN0_BIT | PAD_CHAN1_BIT | PAD_CHAN2_BIT | PAD_CHAN3_BIT;
}
@@ -416,7 +417,9 @@ u32 PADRead(PADStatus* status) {
u32 sr;
int chanShift;
u32 motor;
#if SDK_AUG2010
static PADStatus pre_status[4];
#endif
int threshold;
threshold = 3;
@@ -462,7 +465,7 @@ u32 PADRead(PADStatus* status) {
if (!(SIGetType(chan) & SI_GC_NOMOTOR)) {
motor |= chanBit;
}
if (!SIGetResponse(chan, &data)) {
status->err = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, err));
@@ -470,7 +473,7 @@ u32 PADRead(PADStatus* status) {
status->err = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, err));
} else {
MakeStatus(chan, status, data);
@@ -480,6 +483,7 @@ u32 PADRead(PADStatus* status) {
threshold = 3;
}
#if SDK_AUG2010
#ifdef __MWERKS__
#define abs(x) __abs(x)
#else
@@ -500,19 +504,20 @@ u32 PADRead(PADStatus* status) {
#undef abs
memcpy(&pre_status[chan], status, sizeof(PADStatus));
#endif
// Check and clear PAD_ORIGIN bit
if (status->button & 0x2000) {
status->err = PAD_ERR_TRANSFER;
memset(status, 0, offsetof(PADStatus, err));
// Get origin. It is okay if the following transfer fails
// since the PAD_ORIGIN bit remains until the read origin
// command complete.
SITransfer(chan, &CmdReadOrigin, 1, &Origin[chan], 10, PADOriginUpdateCallback, 0);
} else {
status->err = PAD_ERR_NONE;
// Clear PAD_INTERFERE bit
status->button &= ~0x0080;
}
@@ -690,6 +695,10 @@ static u8 ClampU8(u8 var, u8 org) {
}
static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
#if !SDK_AUG2010 || VERSION == VERSION_SHIELD
static PADStatus pre_status[4];
#endif
s32 threshold;
PADStatus* origin;
status->button = (u16)((data[0] >> 16) & PAD_ALL);
@@ -765,6 +774,29 @@ static void SPEC2_MakeStatus(s32 chan, PADStatus* status, u32 data[2]) {
status->substickY = ClampS8(status->substickY, origin->substickY);
status->triggerLeft = ClampU8(status->triggerLeft, origin->triggerLeft);
status->triggerRight = ClampU8(status->triggerRight, origin->triggerRight);
#if !SDK_AUG2010
#ifdef __MWERKS__
#define abs(x) __abs(x)
#else
#define abs(x) __builtin_abs(x)
#endif
threshold = 9;
if (abs(status->stickX * status->stickX - pre_status[chan].stickX * pre_status[chan].stickX) >= threshold ||
abs(status->stickY * status->stickY - pre_status[chan].stickY * pre_status[chan].stickY) >= threshold ||
abs(status->substickX * status->substickX - pre_status[chan].substickX * pre_status[chan].substickX) >= threshold ||
abs(status->substickY * status->substickY - pre_status[chan].substickY * pre_status[chan].substickY) >= threshold ||
abs(status->triggerLeft * status->triggerLeft - pre_status[chan].triggerLeft * pre_status[chan].triggerLeft) >= threshold ||
abs(status->triggerRight * status->triggerRight - pre_status[chan].triggerRight * pre_status[chan].triggerRight) >= threshold ||
pre_status[chan].button != status->button) {
__VIResetSIIdle();
}
memcpy(&pre_status[chan], status, sizeof(PADStatus));
#endif
#undef abs
}
int PADGetType(s32 chan, u32* type) {
@@ -889,6 +921,6 @@ BOOL PADIsBarrel(s32 chan) {
if (BarrelBits & (PAD_CHAN0_BIT >> chan)) {
return TRUE;
}
return FALSE;
}
+37
View File
@@ -0,0 +1,37 @@
#include <revolution/tpl.h>
#include <revolution/os.h>
void TPLBind(TPLPalettePtr ptr) {
u16 i;
if (ptr->versionNumber != 2142000) {
OSPanic(__FILE__, 0x19, "invalid version number for texture palette");
}
ptr->descriptorArray = (TPLDescriptorPtr)(((u32)(ptr->descriptorArray)) + ((u32)ptr));
for (i = 0; i < ptr->numDescriptors; i++) {
if (ptr->descriptorArray[i].textureHeader) {
ptr->descriptorArray[i].textureHeader = (TPLHeaderPtr)(((u32)(ptr->descriptorArray[i].textureHeader)) + ((u32)ptr));
if (!ptr->descriptorArray[i].textureHeader->unpacked) {
ptr->descriptorArray[i].textureHeader->data = (char*)((u32)(ptr->descriptorArray[i].textureHeader->data) + (u32)ptr);
ptr->descriptorArray[i].textureHeader->unpacked = 1;
}
}
if (ptr->descriptorArray[i].CLUTHeader) {
ptr->descriptorArray[i].CLUTHeader = (TPLClutHeaderPtr)((u32)(ptr->descriptorArray[i].CLUTHeader) + (u32)ptr);
if (!ptr->descriptorArray[i].CLUTHeader->unpacked) {
ptr->descriptorArray[i].CLUTHeader->data = (char*)((u32)(ptr->descriptorArray[i].CLUTHeader->data) + (u32)ptr);
ptr->descriptorArray[i].CLUTHeader->unpacked = 1;
}
}
}
}
TPLDescriptorPtr TPLGet(TPLPalettePtr ptr, u32 id) {
id %= ptr->numDescriptors;
return &ptr->descriptorArray[id];
}