The first commit

This commit is contained in:
Banjo Kazooie
2022-07-15 17:09:41 -05:00
commit dd13d34074
1087 changed files with 391897 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
#include <ultra64.h>
#include "synthInternals.h"
Acmd *alAuxBusPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
ALAuxBus *m = (ALAuxBus *)filter;
ALFilter **sources = m->sources;
s32 i;
/*
* clear the output buffers here
*/
aClearBuffer(ptr++, AL_AUX_L_OUT, outCount<<1);
aClearBuffer(ptr++, AL_AUX_R_OUT, outCount<<1);
for (i = 0; i < m->sourceCount; i++) {
ptr = (sources[i]->handler)(sources[i], outp, outCount, sampleOffset,
ptr);
}
return ptr;
}
s32 alAuxBusParam(void *filter, s32 paramID, void *param)
{
ALAuxBus *m = (ALAuxBus *) filter;
ALFilter **sources = m->sources;
switch (paramID) {
case (AL_FILTER_ADD_SOURCE):
sources[m->sourceCount++] = (ALFilter *) param;
break;
default:
/* ??? */
break;
}
return 0;
}

118
src/core1/done/audio/bnkf.c Normal file
View File

@@ -0,0 +1,118 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
/* copt used??? */
void alSeqFileNew(ALSeqFile *file, u8 *base)
{
s32 offset = (s32) base;
s32 i;
/*
* patch the file so that offsets are pointers
*/
for (i = 0; i < file->seqCount; i++) {
file->seqArray[i].offset = (u8 *)((u8 *)file->seqArray[i].offset + offset);
}
}
static void _bnkfPatchWaveTable(ALWaveTable *w, s32 offset, s32 table)
{
if (w->flags)
return;
w->flags = 1;
w->base += table;
/* sct 2/14/96 - patch wavetable loop info based on type. */
if (w->type == AL_ADPCM_WAVE)
{
w->waveInfo.adpcmWave.book = (ALADPCMBook *)((u8 *)w->waveInfo.adpcmWave.book + offset);
if (w->waveInfo.adpcmWave.loop)
w->waveInfo.adpcmWave.loop = (ALADPCMloop *)((u8 *)w->waveInfo.adpcmWave.loop + offset);
}
else if (w->type == AL_RAW16_WAVE)
{
if (w->waveInfo.rawWave.loop)
w->waveInfo.rawWave.loop = (ALRawLoop *)((u8 *)w->waveInfo.rawWave.loop + offset);
}
}
static void _bnkfPatchSound(ALSound *s, s32 offset, s32 table)
{
if (s->flags)
return;
s->flags = 1;
s->envelope = (ALEnvelope *)((u8 *)s->envelope + offset);
s->keyMap = (ALKeyMap *)((u8 *)s->keyMap + offset);
s->wavetable = (ALWaveTable *)((u8 *)s->wavetable + offset);
_bnkfPatchWaveTable(s->wavetable, offset, table);
}
static void _bnkfPatchInst(ALInstrument *inst, s32 offset, s32 table)
{
s32 i;
if (inst->flags)
return;
inst->flags = 1;
for (i = 0; i < inst->soundCount; i++) {
inst->soundArray[i] = (ALSound *)((u8 *)inst->soundArray[i] +
offset);
_bnkfPatchSound(inst->soundArray[i], offset, table);
}
}
static void _bnkfPatchBank(ALBank *bank, s32 offset, s32 table)
{
s32 i;
if (bank->flags)
return;
bank->flags = 1;
if (bank->percussion) {
bank->percussion = (ALInstrument *)((u8 *)bank->percussion + offset);
_bnkfPatchInst(bank->percussion, offset, table);
}
for (i = 0; i < bank->instCount; i++) {
bank->instArray[i] = (ALInstrument *)((u8 *)bank->instArray[i] +
offset);
if(bank->instArray[i])
_bnkfPatchInst(bank->instArray[i], offset, table);
}
}
void alBnkfNew(ALBankFile *file, u8 *table)
{
s32 offset = (s32) file;
s32 woffset = (s32) table;
s32 i;
/*
* check the file format revision in debug libraries
*/
ALFailIf(file->revision != AL_BANK_VERSION, ERR_ALBNKFNEW);
/*
* patch the file so that offsets are pointers
*/
for (i = 0; i < file->bankCount; i++) {
file->bankArray[i] = (ALBank *)((u8 *)file->bankArray[i] + offset);
if(file->bankArray[i])
_bnkfPatchBank(file->bankArray[i], offset, woffset);
}
}

View File

@@ -0,0 +1,23 @@
#include <libaudio.h>
f32 alCents2Ratio(s32 cents)
{
f32 x;
f32 ratio = 1.0f;
if (cents >= 0) {
x = 1.00057779f; /* 2^(1/1200) */
} else {
x = 0.9994225441f; /* 2^(-1/1200) */
cents = -cents;
}
while (cents) {
if (cents & 1)
ratio *= x;
x *= x;
cents >>= 1;
}
return ratio;
}

View File

@@ -0,0 +1,14 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void func_8025F3F0(ALCSPlayer *seqp, f32 arg1, f32 arg2)
{
ALEvent evt;
evt.type = AL_UNK18_EVT; //event type not listed;
evt.msg.unk18.unk0 = arg1;
evt.msg.unk18.unk4 = arg2;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,9 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
u8 func_8025F4A0(N_ALCSPlayer *seqp, u8 chan)
{
return seqp->chanState[chan].unk9;
}

View File

@@ -0,0 +1,16 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void func_8025F510(ALCSPlayer *seqp, u8 chan, u8 arg2)
{
ALEvent evt;
evt.type = AL_SEQP_MIDI_EVT;
evt.msg.midi.ticks = 0;
evt.msg.midi.status = AL_MIDI_ControlChange | chan;
evt.msg.midi.byte1 = 0x7D;
evt.msg.midi.byte2 = arg2;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,40 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
void func_8025F610(void){
n_syn->head = NULL;
n_syn->n_seqp1 = NULL;
n_syn->n_seqp2 = NULL;
n_syn->unk5C = NULL;
n_syn->unk60 = NULL;
n_syn->unk64 = NULL;
n_syn->unk68 = NULL;
n_syn->unk6C = NULL;
n_syn->unk70 = NULL;
n_syn->n_sndp = NULL;
}
void func_8025F5C0(N_ALSeqPlayer *arg0, u8 arg1){
ALEvent evt;
evt.type = AL_SEQP_MIDI_EVT;
evt.msg.midi.ticks = 0;
evt.msg.midi.status = AL_MIDI_ChannelModeSelect;
evt.msg.midi.byte1 = 0x7E;
evt.msg.midi.byte2 = arg1;
alEvtqPostEvent(&arg0->evtq, &evt, 0);
}
void func_8025F570(N_ALSeqPlayer *arg0, u8 arg1){
ALEvent evt;
evt.type = AL_SEQP_MIDI_EVT;
evt.msg.midi.ticks = 0;
evt.msg.midi.status = AL_MIDI_ChannelModeSelect;
evt.msg.midi.byte1 = 0x7F;
evt.msg.midi.byte2 = arg1;
alEvtqPostEvent(&arg0->evtq, &evt, 0);
}

View File

@@ -0,0 +1,14 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alCopy(void *src, void *dest, s32 len)
{
s32 i;
u8 *s = (u8 *)src;
u8 *d = (u8 *)dest;
for (i = 0; i < len; i++){
*d++ = *s++;
}
}

375
src/core1/done/audio/cseq.c Normal file
View File

@@ -0,0 +1,375 @@
#include <ultra64.h>
static u32 __readVarLen(ALCSeq *s,u32 track);
static u8 __getTrackByte(ALCSeq *s,u32 track);
static u32 __alCSeqGetTrackEvent(ALCSeq *seq, u32 track, ALEvent *event);
void alCSeqNew(ALCSeq *seq, u8 *ptr)
{
u32 i,tmpOff,flagTmp;
/* load the seqence pointed to by ptr */
seq->base = (ALCMidiHdr*)ptr;
seq->validTracks = 0;
seq->lastDeltaTicks = 0;
seq->lastTicks = 0;
seq->deltaFlag = 1;
for(i = 0; i < 16; i++)
{
seq->lastStatus[i] = 0;
seq->curBUPtr[i] = 0;
seq->curBULen[i] = 0;
tmpOff = seq->base->trackOffset[i];
if(tmpOff) /* if the track is valid */
{
flagTmp = 1 << i;
seq->validTracks |= flagTmp;
seq->curLoc[i] = (u8*)((u32)ptr + tmpOff);
seq->evtDeltaTicks[i] = __readVarLen(seq,i);
/*__alCSeqGetTrackEvent(seq,i); prime the event buffers */
}
else
seq->curLoc[i] = 0;
}
seq->qnpt = 1.0/(f32)seq->base->division;
}
void alCSeqNextEvent(ALCSeq *seq,ALEvent *evt)
{
u32 i;
u32 firstTime = 0xFFFFFFFF;
u32 firstTrack;
u32 lastTicks = seq->lastDeltaTicks;
#ifdef _DEBUG
/* sct 1/17/96 - Warn if we are beyond the end of sequence. */
if (!seq->validTracks)
__osError(ERR_ALSEQOVERRUN, 0);
#endif
for(i = 0; i < 16 ; i++)
{
if((seq->validTracks >> i) & 1)
{
if(seq->deltaFlag)
seq->evtDeltaTicks[i] -= lastTicks;
if(seq->evtDeltaTicks[i] < firstTime)
{
firstTime = seq->evtDeltaTicks[i];
firstTrack = i;
}
}
}
__alCSeqGetTrackEvent(seq,firstTrack,evt);
evt->msg.midi.ticks = firstTime;
seq->lastTicks += firstTime;
seq->lastDeltaTicks = firstTime;
if(evt->type != AL_TRACK_END)
seq->evtDeltaTicks[firstTrack] += __readVarLen(seq,firstTrack);
seq->deltaFlag = 1;
}
/*
Note: If there are no valid tracks (ie. all tracks have
reached the end of their data stream), then return FALSE
to indicate that there is no next event.
*/
char __alCSeqNextDelta(ALCSeq *seq, s32 *pDeltaTicks)
{
u32 i;
u32 firstTime = 0xFFFFFFFF;
u32 lastTicks = seq->lastDeltaTicks;
if (!seq->validTracks)
return FALSE;
for(i = 0; i < 16 ; i++)
{
if((seq->validTracks >> i) & 1)
{
if(seq->deltaFlag)
seq->evtDeltaTicks[i] -= lastTicks;
if(seq->evtDeltaTicks[i] < firstTime)
firstTime = seq->evtDeltaTicks[i];
}
}
seq->deltaFlag = 0;
*pDeltaTicks = firstTime;
return TRUE;
}
/* only call alCSeqGetTrackEvent with a valid track !! */
static u32 __alCSeqGetTrackEvent(ALCSeq *seq, u32 track, ALEvent *event)
{
u32 offset;
u8 status, loopCt, curLpCt, *tmpPtr;
status = __getTrackByte(seq,track); /* read the status byte */
if (status == AL_MIDI_Meta) /* running status not allowed on meta events!! */
{
u8 type = __getTrackByte(seq,track);
if (type == AL_MIDI_META_TEMPO)
{
event->type = AL_TEMPO_EVT;
event->msg.tempo.status = status;
event->msg.tempo.type = type;
event->msg.tempo.byte1 = __getTrackByte(seq,track);
event->msg.tempo.byte2 = __getTrackByte(seq,track);
event->msg.tempo.byte3 = __getTrackByte(seq,track);
seq->lastStatus[track] = 0; /* lastStatus not supported after meta */
}
else if (type == AL_MIDI_META_EOT)
{
u32 flagMask;
flagMask = 0x01 << track;
seq->validTracks = seq->validTracks ^ flagMask;
if(seq->validTracks) /* there is music left don't end */
event->type = AL_TRACK_END;
else /* no more music send AL_SEQ_END_EVT msg */
event->type = AL_SEQ_END_EVT;
}
else if (type == AL_CMIDI_LOOPSTART_CODE)
{
status = __getTrackByte(seq,track); /* get next two bytes, ignore them */
status = __getTrackByte(seq,track);
seq->lastStatus[track] = 0;
event->type = AL_CSP_LOOPSTART;
}
else if (type == AL_CMIDI_LOOPEND_CODE)
{
tmpPtr = seq->curLoc[track];
loopCt = *tmpPtr++;
curLpCt = *tmpPtr;
if(curLpCt == 0) /* done looping */
{
*tmpPtr = loopCt; /* reset current loop count */
seq->curLoc[track] = tmpPtr + 5; /* move pointer to end of event */
}
else
{
if(curLpCt != 0xFF) /* not a loop forever */
*tmpPtr = curLpCt - 1; /* decrement current loop count */
tmpPtr++; /* get offset from end of event */
offset = (*tmpPtr++) << 24;
offset += (*tmpPtr++) << 16;
offset += (*tmpPtr++) << 8;
offset += *tmpPtr++;
seq->curLoc[track] = tmpPtr - offset;
}
seq->lastStatus[track] = 0;
event->type = AL_CSP_LOOPEND;
}
#ifdef _DEBUG
else
__osError(ERR_ALSEQMETA, 1, type);
#endif
}
else
{
event->type = AL_SEQ_MIDI_EVT;
if (status & 0x80) /* if high bit is set, then new status */
{
event->msg.midi.status = status;
event->msg.midi.byte1 = __getTrackByte(seq,track);
seq->lastStatus[track] = status;
}
else /* running status */
{
#ifdef _DEBUG
if(seq->lastStatus[track] == 0)
__osError(ERR_ALCSEQZEROSTATUS, 1, track);
#endif
event->msg.midi.status = seq->lastStatus[track];
event->msg.midi.byte1 = status;
}
if (((event->msg.midi.status & 0xf0) != AL_MIDI_ProgramChange) &&
((event->msg.midi.status & 0xf0) != AL_MIDI_ChannelPressure))
{
event->msg.midi.byte2 = __getTrackByte(seq,track);
if((event->msg.midi.status & 0xf0) == AL_MIDI_NoteOn)
{
event->msg.midi.duration = __readVarLen(seq,track);
#ifdef _DEBUG
if(event->msg.midi.byte2 == 0)
__osError( ERR_ALCSEQZEROVEL, 1, track);
#endif
}
}
else
event->msg.midi.byte2 = 0;
}
return TRUE;
}
f32 alCSeqTicksToSec(ALCSeq *seq, s32 ticks, u32 tempo)
{
return ((f32) (((f32)(ticks) * (f32)(tempo)) /
((f32)(seq->base->division) * 1000000.0)));
}
u32 alCSeqSecToTicks(ALCSeq *seq, f32 sec, u32 tempo)
{
return (u32)(((sec * 1000000.0) * seq->base->division) / tempo);
}
s32 alCSeqGetTicks(ALCSeq *seq)
{
return seq->lastTicks;
}
void alCSeqNewMarker(ALCSeq *seq, ALCSeqMarker *m, u32 ticks)
{
ALEvent evt;
ALCSeq tempSeq;
s32 i;
alCSeqNew(&tempSeq, (u8*)seq->base);
do {
m->validTracks = tempSeq.validTracks;
m->lastTicks = tempSeq.lastTicks;
m->lastDeltaTicks = tempSeq.lastDeltaTicks;
for(i=0;i<16;i++)
{
m->curLoc[i] = tempSeq.curLoc[i];
m->curBUPtr[i] = tempSeq.curBUPtr[i];
m->curBULen[i] = tempSeq.curBULen[i];
m->lastStatus[i] = tempSeq.lastStatus[i];
m->evtDeltaTicks[i] = tempSeq.evtDeltaTicks[i];
}
alCSeqNextEvent(&tempSeq, &evt);
if (evt.type == AL_SEQ_END_EVT)
break;
} while (tempSeq.lastTicks < ticks);
}
void alCSeqSetLoc(ALCSeq *seq, ALCSeqMarker *m)
{
s32 i;
seq->validTracks = m->validTracks;
seq->lastTicks = m->lastTicks;
seq->lastDeltaTicks = m->lastDeltaTicks;
for(i=0;i<16;i++)
{
seq->curLoc[i] = m->curLoc[i];
seq->curBUPtr[i] = m->curBUPtr[i];
seq->curBULen[i] = m->curBULen[i];
seq->lastStatus[i] = m->lastStatus[i];
seq->evtDeltaTicks[i] = m->evtDeltaTicks[i];
}
}
void alCSeqGetLoc(ALCSeq *seq, ALCSeqMarker *m)
{
s32 i;
m->validTracks = seq->validTracks;
m->lastTicks = seq->lastTicks;
m->lastDeltaTicks = seq->lastDeltaTicks;
for(i=0;i<16;i++)
{
m->curLoc[i] = seq->curLoc[i];
m->curBUPtr[i] = seq->curBUPtr[i];
m->curBULen[i] = seq->curBULen[i];
m->lastStatus[i] = seq->lastStatus[i];
m->evtDeltaTicks[i] = seq->evtDeltaTicks[i];
}
}
/* non-aligned byte reading routines */
static u8 __getTrackByte(ALCSeq *seq,u32 track)
{
u8 theByte;
if(seq->curBULen[track])
{
theByte = *seq->curBUPtr[track];
seq->curBUPtr[track]++;
seq->curBULen[track]--;
}
else /* need to handle backup mode */
{
theByte = *seq->curLoc[track];
seq->curLoc[track]++;
if(theByte == AL_CMIDI_BLOCK_CODE)
{
u8 loBackUp,hiBackUp,theLen,nextByte;
u32 backup;
nextByte = *seq->curLoc[track];
seq->curLoc[track]++;
if(nextByte != AL_CMIDI_BLOCK_CODE)
{
/* if here, then got a backup section. get the amount of
backup, and the len of the section. Subtract the amount of
backup from the curLoc ptr, and subtract four more, since
curLoc has been advanced by four while reading the codes. */
hiBackUp = nextByte;
loBackUp = *seq->curLoc[track];
seq->curLoc[track]++;
theLen = *seq->curLoc[track];
seq->curLoc[track]++;
backup = (u32)hiBackUp;
backup = backup << 8;
backup += loBackUp;
seq->curBUPtr[track] = seq->curLoc[track] - (backup + 4);
seq->curBULen[track] = (u32)theLen;
/* now get the byte */
theByte = *seq->curBUPtr[track];
seq->curBUPtr[track]++;
seq->curBULen[track]--;
}
}
}
return theByte;
}
static u32 __readVarLen(ALCSeq *seq,u32 track)
{
u32 value;
u32 c;
value = (u32)__getTrackByte(seq,track);
if ( value & 0x00000080 )
{
value &= 0x7f;
do
{
c = (u32)__getTrackByte(seq,track);
value = (value << 7) + (c & 0x7f);
} while (c & 0x80);
}
return (value);
}

View File

@@ -0,0 +1,10 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
s32 alCSPGetTempo(ALCSPlayer *seqp){
if(seqp->target == NULL)
return 0;
return seqp->uspt / seqp->target->qnpt;
}

View File

@@ -0,0 +1,12 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alCSPPlay(ALCSPlayer *seqp)
{
ALEvent evt;
evt.type = AL_SEQP_PLAY_EVT;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,13 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alCSPSetBank(ALCSPlayer *seqp, ALBank *b)
{
ALEvent evt;
evt.type = AL_SEQP_BANK_EVT;
evt.msg.spbank.bank = b;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,11 @@
#include <ultra64.h>
void alCSPSetSeq(ALCSPlayer *seqp, ALCSeq *seq)
{
ALEvent evt;
evt.type = AL_SEQP_SEQ_EVT;
evt.msg.spseq.seq = seq;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,17 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alCSPSetTempo(ALCSPlayer *seqp, s32 tempo)
{
ALEvent evt;
evt.type = AL_SEQP_META_EVT;
evt.msg.tempo.status = AL_MIDI_Meta;
evt.msg.tempo.type = AL_MIDI_META_TEMPO;
evt.msg.tempo.byte1 = (tempo & 0xff0000)>>16;
evt.msg.tempo.byte2 = (tempo & 0xff00)>>8;
evt.msg.tempo.byte3 = tempo & 0xff;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,15 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alCSPSetVol(ALCSPlayer *seqp, s16 vol)
{
ALEvent evt;
evt.type = AL_SEQP_VOL_EVT;
evt.msg.spvol.vol = vol;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,10 @@
#include <ultra64.h>
void alCSPStop(ALCSPlayer *seqp)
{
ALEvent evt;
evt.type = AL_SEQP_STOPPING_EVT;
alEvtqPostEvent(&seqp->evtq, &evt, 0);
}

View File

@@ -0,0 +1,280 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "synthInternals.h"
/*
* WARNING: THE FOLLOWING CONSTANT MUST BE KEPT IN SYNC
* WITH SCALING IN MICROCODE!!!
*/
#define SCALE 16384
/*
* the following arrays contain default parameters for
* a few hopefully useful effects.
*/
#define ms *(((s32)((f32)44.1))&~0x7)
static s32 SMALLROOM_PARAMS[26] = {
/* sections length */
3, 100 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 54 ms, 9830, -9830, 0, 0, 0, 0,
19 ms, 38 ms, 3276, -3276, 0x3fff, 0, 0, 0,
0, 60 ms, 5000, 0, 0, 0, 0, 0x5000
};
static s32 BIGROOM_PARAMS[34] = {
/* sections length */
4, 100 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 66 ms, 9830, -9830, 0, 0, 0, 0,
22 ms, 54 ms, 3276, -3276, 0x3fff, 0, 0, 0,
66 ms, 91 ms, 3276, -3276, 0x3fff, 0, 0, 0,
0, 94 ms, 8000, 0, 0, 0, 0, 0x5000
};
static s32 ECHO_PARAMS[10] = {
/* sections length */
1, 200 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 179 ms, 12000, 0, 0x7fff, 0, 0, 0
};
static s32 CHORUS_PARAMS[10] = {
/* sections length */
1, 20 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 5 ms, 0x4000, 0, 0x7fff, 7600, 700, 0
};
static s32 FLANGE_PARAMS[10] = {
/* sections length */
1, 20 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 5 ms, 0, 0x5fff, 0x7fff, 380, 500, 0
};
static s32 NULL_PARAMS[10] = {
0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
void init_lpfilter(ALLowPass *lp)
{
s32 i, temp;
s16 fc;
f64 ffc, fcoef;
temp = lp->fc * SCALE;
fc = temp >> 15;
lp->fgain = SCALE - fc;
lp->first = 1;
for (i=0; i<8; i++)
lp->fcvec.fccoef[i] = 0;
lp->fcvec.fccoef[i++] = fc;
fcoef = ffc = (f64)fc/SCALE;
for (; i<16; i++){
fcoef *= ffc;
lp->fcvec.fccoef[i] = (s16)(fcoef * SCALE);
}
}
void alFxNew(ALFx *r, ALSynConfig *c, ALHeap *hp)
{
u16 i, j, k;
s32 *param = 0;
ALFilter *f = (ALFilter *) r;
ALDelay *d;
alFilterNew(f, 0, alFxParam, AL_FX);
f->handler = alFxPull;
r->paramHdl = (ALSetFXParam)alFxParamHdl;
switch (c->fxType) {
case AL_FX_SMALLROOM: param = SMALLROOM_PARAMS; break;
case AL_FX_BIGROOM: param = BIGROOM_PARAMS; break;
case AL_FX_ECHO: param = ECHO_PARAMS; break;
case AL_FX_CHORUS: param = CHORUS_PARAMS; break;
case AL_FX_FLANGE: param = FLANGE_PARAMS; break;
case AL_FX_CUSTOM: param = c->params; break;
default: param = NULL_PARAMS; break;
}
j = 0;
r->section_count = param[j++];
r->length = param[j++];
r->delay = alHeapAlloc(hp, r->section_count, sizeof(ALDelay));
r->base = alHeapAlloc(hp, r->length, sizeof(s16));
r->input = r->base;
for ( k=0; k < r->length; k++)
r->base[k] = 0;
for ( i=0; i<r->section_count; i++ ){
d = &r->delay[i];
d->input = param[j++];
d->output = param[j++];
d->fbcoef = param[j++];
d->ffcoef = param[j++];
d->gain = param[j++];
if (param[j]) {
#define RANGE 2.0
/* d->rsinc = ((f32) param[j++])/0xffffff; */
d->rsinc = ((((f32)param[j++])/1000) * RANGE)/c->outputRate;
/*
* the following constant is derived from:
*
* ratio = 2^(cents/1200)
*
* and therefore for hundredths of a cent
* x
* ln(ratio) = ---------------
* (120,000)/ln(2)
* where
* 120,000/ln(2) = 173123.40...
*/
#define CONVERT 173123.404906676
#define LENGTH (d->output - d->input)
d->rsgain = (((f32) param[j++])/CONVERT) * LENGTH;
d->rsval = 1.0;
d->rsdelta = 0.0;
d->rs = alHeapAlloc(hp, 1, sizeof(ALResampler));
d->rs->state = alHeapAlloc(hp, 1, sizeof(RESAMPLE_STATE));
d->rs->delta = 0.0;
d->rs->first = 1;
} else {
d->rs = 0;
j++;
j++;
}
if (param[j]) {
d->lp = alHeapAlloc(hp, 1, sizeof(ALLowPass));
d->lp->fstate = alHeapAlloc(hp, 1, sizeof(POLEF_STATE));
d->lp->fc = param[j++];
init_lpfilter(d->lp);
} else {
d->lp = 0;
j++;
}
}
}
void alEnvmixerNew(ALEnvMixer *e, ALHeap *hp)
{
alFilterNew((ALFilter *) e, alEnvmixerPull, alEnvmixerParam, AL_ENVMIX);
e->state = alHeapAlloc(hp, 1, sizeof(ENVMIX_STATE));
e->first = 1;
e->motion = AL_STOPPED;
e->volume = 1;
e->ltgt = 1;
e->rtgt = 1;
e->cvolL = 1;
e->cvolR = 1;
e->dryamt = 0;
e->wetamt = 0;
e->lratm = 1;
e->lratl = 0;
e->lratm = 1;
e->lratl = 0;
e->delta = 0;
e->segEnd = 0;
e->pan = 0;
e->ctrlList = 0;
e->ctrlTail = 0;
e->sources = 0;
}
void alLoadNew(ALLoadFilter *f, ALDMANew dmaNew, ALHeap *hp)
{
s32
i;
/*
* init filter superclass
*/
alFilterNew((ALFilter *) f, alAdpcmPull, alLoadParam, AL_ADPCM);
f->state = alHeapAlloc(hp, 1, sizeof(ADPCM_STATE));
f->lstate = alHeapAlloc(hp, 1, sizeof(ADPCM_STATE));
f->dma = dmaNew(&f->dmaState);
/*
* init the adpcm state
*/
f->lastsam = 0;
f->first = 1;
f->memin = 0;
}
void alResampleNew(ALResampler *r, ALHeap *hp)
{
alFilterNew((ALFilter *) r, alResamplePull, alResampleParam, AL_RESAMPLE);
/*
* Init resampler state
*/
r->state = alHeapAlloc(hp, 1, sizeof(RESAMPLE_STATE));
r->delta = 0.0;
r->first = 1;
r->motion = AL_STOPPED;
r->ratio = 1.0;
r->upitch = 0;
r->ctrlList = 0;
r->ctrlTail = 0;
/* state in the ucode is initialized by the A_INIT flag */
}
void alAuxBusNew(ALAuxBus *m, void *sources, s32 maxSources)
{
alFilterNew((ALFilter *) m, alAuxBusPull, alAuxBusParam, AL_AUXBUS);
m->sourceCount = 0;
m->maxSources = maxSources;
m->sources = (ALFilter **)sources;
}
void alMainBusNew(ALMainBus *m, void *sources, s32 maxSources)
{
alFilterNew((ALFilter *) m, alMainBusPull, alMainBusParam, AL_MAINBUS);
m->sourceCount = 0;
m->maxSources = maxSources;
m->sources = (ALFilter **)sources;
}
void alSaveNew(ALSave *f)
{
/*
* init filter superclass
*/
alFilterNew((ALFilter *) f, alSavePull, alSaveParam, AL_SAVE);
/*
* init the save state, which is a virtual dram address
*/
f->dramout = 0;
f->first = 1;
}

495
src/core1/done/audio/env.c Normal file
View File

@@ -0,0 +1,495 @@
#include <ultra64.h>
#include "synthInternals.h"
#ifndef assert
#define assert(s)
#endif
#ifdef AUD_PROFILE
extern u32 cnt_index, env_num, env_cnt, env_max, env_min, lastCnt[];
extern u32 rate_num, rate_cnt, rate_max, rate_min;
extern u32 vol_num, vol_cnt, vol_max, vol_min;
#endif
#define EQPOWER_LENGTH 128
static s16 eqpower[ EQPOWER_LENGTH ] = {
32767, 32764, 32757, 32744, 32727, 32704,
32677, 32644, 32607, 32564, 32517, 32464,
32407, 32344, 32277, 32205, 32127, 32045,
31958, 31866, 31770, 31668, 31561, 31450,
31334, 31213, 31087, 30957, 30822, 30682,
30537, 30388, 30234, 30075, 29912, 29744,
29572, 29395, 29214, 29028, 28838, 28643,
28444, 28241, 28033, 27821, 27605, 27385,
27160, 26931, 26698, 26461, 26220, 25975,
25726, 25473, 25216, 24956, 24691, 24423,
24151, 23875, 23596, 23313, 23026, 22736,
22442, 22145, 21845, 21541, 21234, 20924,
20610, 20294, 19974, 19651, 19325, 18997,
18665, 18331, 17993, 17653, 17310, 16965,
16617, 16266, 15913, 15558, 15200, 14840,
14477, 14113, 13746, 13377, 13006, 12633,
12258, 11881, 11503, 11122, 10740, 10357,
9971, 9584, 9196, 8806, 8415, 8023,
7630, 7235, 6839, 6442, 6044, 5646,
5246, 4845, 4444, 4042, 3640, 3237,
2833, 2429, 2025, 1620, 1216, 810,
405, 0
};
extern f64 __pow(f64, f64);
/*
* prototypes for private enveloper functions
*/
static Acmd *_pullSubFrame(void *filter, s16 *inp, s16 *outp, s32 outCount,
s32 sampleOffset, Acmd *p) ;
static s16 _getRate(f64 vol, f64 tgt, s32 count, u16* ratel);
static f32 _getVol(f32 ivol, s32 samples, s16 ratem, u16 ratel);
/***********************************************************************
* Enveloper filter public interfaces
***********************************************************************/
Acmd *alEnvmixerPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset,
Acmd *p)
{
Acmd *ptr = p;
ALEnvMixer *e = (ALEnvMixer *)filter;
s16 inp;
s32 lastOffset;
s32 thisOffset = sampleOffset;
s32 samples;
s16 loutp = 0;
s32 fVol;
ALParam *thisParam;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
/*
* Force the input to be the resampler output
*/
inp = AL_RESAMPLER_OUT;
while (e->ctrlList != 0) {
lastOffset = thisOffset;
thisOffset = e->ctrlList->delta;
samples = thisOffset - lastOffset;
if (samples > outCount)
break;
assert(samples >= 0);
assert(samples <= AL_MAX_RSP_SAMPLES);
switch (e->ctrlList->type) {
case (AL_FILTER_START_VOICE_ALT):
{
ALStartParamAlt *param = (ALStartParamAlt *)e->ctrlList;
ALFilter *f = (ALFilter *) e;
s32 tmp;
if (param->unity) {
(*e->filter.setParam)(&e->filter,
AL_FILTER_SET_UNITY_PITCH, 0);
}
(*e->filter.setParam)(&e->filter, AL_FILTER_SET_WAVETABLE,
param->wave);
(*e->filter.setParam)(&e->filter, AL_FILTER_START, 0);
e->first = 1;
e->delta = 0;
e->segEnd = param->samples;
tmp = ((s32)param->volume + (s32)param->volume) /2;
//tmp = ((s32)param->volume * (s32)param->volume) >> 15;
e->volume = (s16) tmp;
e->pan = param->pan;
e->dryamt = eqpower[param->fxMix];
e->wetamt = eqpower[EQPOWER_LENGTH - param->fxMix - 1];
if (param->samples) {
e->cvolL = 1;
e->cvolR = 1;
} else {
/*
* Attack time is zero. Simply set the
* volume. We don't want an attack segment.
*/
e->cvolL = (e->volume * eqpower[e->pan]) >> 15;
e->cvolR = (e->volume *
eqpower[EQPOWER_LENGTH - e->pan - 1]) >> 15;
}
if (f->source) {
union {
f32 f;
s32 i;
} data;
data.f = param->pitch;
(*f->source->setParam)(f->source, AL_FILTER_SET_PITCH,
(void *)data.i);
}
}
break;
case (AL_FILTER_SET_FXAMT):
case (AL_FILTER_SET_PAN):
case (AL_FILTER_SET_VOLUME):
ptr = _pullSubFrame(e, &inp, &loutp, samples, sampleOffset, ptr);
e->delta += samples;
if (e->delta >= e->segEnd){
/*
* We should have reached our target, calculate
* target in case e->segEnd was 0
*/
e->ltgt = (e->volume * eqpower[e->pan]) >> 15;
e->rtgt = (e->volume *
eqpower[EQPOWER_LENGTH - e->pan - 1]) >> 15;
e->delta = e->segEnd; /* To prevent overflow */
e->cvolL = e->ltgt;
e->cvolR = e->rtgt;
} else {
/*
* Estimate the current volume
*/
e->cvolL = _getVol(e->cvolL, e->delta, e->lratm, e->lratl);
e->cvolR = _getVol(e->cvolR, e->delta, e->rratm, e->rratl);
}
/*
* We can't have volume of zero, because the envelope
* would never go anywhere from there
*/
if( e->cvolL == 0 ) e->cvolL = 1;
if( e->cvolR == 0 ) e->cvolR = 1;
if (e->ctrlList->type == AL_FILTER_SET_PAN)
/*
* This should result in a change to the current
* segment rate and target
*/
e->pan = (s16) e->ctrlList->data.i;
if (e->ctrlList->type == AL_FILTER_SET_VOLUME){
/*
* Switching to a new segment
*/
e->delta = 0;
/*
* Map volume non-linearly to give something close to
* loudness
*/
fVol = (e->ctrlList->data.i);
//fVol = (fVol*fVol)>>15;
fVol = (fVol+fVol)/2;
e->volume = (s16) fVol;
e->segEnd = e->ctrlList->moredata.i;
}
if (e->ctrlList->type == AL_FILTER_SET_FXAMT){
e->dryamt = eqpower[e->ctrlList->data.i];
e->wetamt = eqpower[EQPOWER_LENGTH - e->ctrlList->data.i - 1];
}
/*
* Force a volume update
*/
e->first = 1;
break;
case (AL_FILTER_START_VOICE):
{
ALStartParam *p = (ALStartParam *)e->ctrlList;
/*
* Changing to PLAYING (since the previous state was
* persumable STOPPED, we'll just bump the output
* pointer rather than pull a subframe of zeros).
*/
if (p->unity) {
(*e->filter.setParam)(&e->filter,
AL_FILTER_SET_UNITY_PITCH, 0);
}
(*e->filter.setParam)(&e->filter, AL_FILTER_SET_WAVETABLE,
p->wave);
(*e->filter.setParam)(&e->filter, AL_FILTER_START, 0);
}
break;
case (AL_FILTER_STOP_VOICE):
{
/*
* Changing to STOPPED and reset the filter
*/
ptr = _pullSubFrame(e, &inp, &loutp, samples, sampleOffset, ptr);
(*e->filter.setParam)(&e->filter, AL_FILTER_RESET, 0);
}
break;
case (AL_FILTER_FREE_VOICE):
{
ALSynth *drvr = &alGlobals->drvr;
ALFreeParam *param = (ALFreeParam *)e->ctrlList;
param->pvoice->offset = 0;
_freePVoice(drvr, (PVoice *)param->pvoice);
}
break;
default:
/*
* Pull the reuired number of samples and then pass the message
* on down the chain
*/
ptr = _pullSubFrame(e, &inp, &loutp, samples, sampleOffset, ptr);
e->delta += samples;
(*e->filter.setParam)(&e->filter, e->ctrlList->type,
(void *) e->ctrlList->data.i);
break;
}
loutp += (samples<<1);
outCount -= samples;
/*
* put the param record back on the free list
*/
thisParam = e->ctrlList;
e->ctrlList = e->ctrlList->next;
if (e->ctrlList == 0)
e->ctrlTail = 0;
__freeParam(thisParam);
}
if(e->motion == 1){
ptr = _pullSubFrame(e, &inp, &loutp, outCount, sampleOffset, ptr);
e->delta += outCount;
}
/*
* Prevent overflow in e->delta
*/
if (e->delta > e->segEnd)
e->delta = e->segEnd;
#ifdef AUD_PROFILE
PROFILE_AUD(env_num, env_cnt, env_max, env_min);
#endif
return ptr;
}
s32
alEnvmixerParam(void *filter, s32 paramID, void *param)
{
ALFilter *f = (ALFilter *) filter;
ALEnvMixer *e = (ALEnvMixer *) filter;
switch (paramID) {
case (AL_FILTER_ADD_UPDATE):
if (e->ctrlTail) {
e->ctrlTail->next = (ALParam *)param;
} else {
e->ctrlList = (ALParam *)param;
}
e->ctrlTail = (ALParam *)param;
break;
case (AL_FILTER_RESET):
e->first = 1;
e->motion = AL_STOPPED;
e->volume = 1;
if (f->source)
(*f->source->setParam)(f->source, AL_FILTER_RESET, param);
break;
case (AL_FILTER_START):
e->motion = AL_PLAYING;
if (f->source)
(*f->source->setParam)(f->source, AL_FILTER_START, param);
break;
case (AL_FILTER_SET_SOURCE):
f->source = (ALFilter *) param;
break;
default:
if (f->source)
(*f->source->setParam)(f->source, paramID, param);
}
return 0;
}
static
Acmd* _pullSubFrame(void *filter, s16 *inp, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
ALEnvMixer *e = (ALEnvMixer *)filter;
ALFilter *source= e->filter.source;
/* filter must be playing and request non-zero output samples to pull. */
//if (e->motion != AL_PLAYING || !outCount)
// return ptr;
if(!outCount)
return ptr;
/*
* ask all filters upstream from us to build their command
* lists.
*/
assert(source);
ptr = (*source->handler)(source, inp, outCount, sampleOffset, p);
/*
* construct our portion of the command list
*/
aSetBuffer(ptr++, A_MAIN, *inp, AL_MAIN_L_OUT + *outp, outCount<<1);
aSetBuffer(ptr++, A_AUX, AL_MAIN_R_OUT + *outp, AL_AUX_L_OUT + *outp,
AL_AUX_R_OUT + *outp);
if (e->first){
e->first = 0;
/*
* Calculate derived parameters
*/
e->ltgt = (e->volume * eqpower[e->pan]) >> 15;
e->lratm = _getRate((f64)e->cvolL, (f64)e->ltgt,
e->segEnd, &(e->lratl));
e->rtgt = (e->volume *
eqpower[EQPOWER_LENGTH - e->pan - 1]) >> 15;
e->rratm = _getRate((f64)e->cvolR, (f64)e->rtgt, e->segEnd,
&(e->rratl));
aSetVolume(ptr++, A_LEFT | A_VOL, e->cvolL, 0, 0);
aSetVolume(ptr++, A_RIGHT | A_VOL, e->cvolR, 0, 0);
aSetVolume(ptr++, A_LEFT | A_RATE, e->ltgt, e->lratm, e->lratl);
aSetVolume(ptr++, A_RIGHT | A_RATE, e->rtgt, e->rratm, e->rratl);
aSetVolume(ptr++, A_AUX, e->dryamt, 0, e->wetamt);
aEnvMixer (ptr++, A_INIT | A_AUX, osVirtualToPhysical(e->state));
}
else
aEnvMixer(ptr++, A_CONTINUE | A_AUX, osVirtualToPhysical(e->state));
/*
* bump the input buffer pointer
*/
*inp += (outCount<<1);
//e->delta += outCount;
return ptr;
}
#define EXP_MASK 0x7f800000
#define MANT_MASK 0x807fffff
f64
_frexpf(f64 value, s32 *eptr)
{
f64 absvalue;
*eptr = 0;
if (value == 0.0) /* nothing to do for zero */
return (value);
absvalue = (value > 0.0) ? value : -value;
for ( ; absvalue >= 1.0; absvalue *= 0.5)
++*eptr;
for ( ; absvalue < 0.5; absvalue += absvalue)
--*eptr;
return (value > 0.0 ? absvalue : -absvalue);
}
f64
_ldexpf(f64 in, s32 ex)
{
s32 exp;
if ( ex ) {
exp = 1 << ex;
in *= (f64)exp;
}
return ( in );
}
/*
_getRate() -- This function determines how to go from the
current volume level (vol) to the target
volume level (tgt) in some number of steps
(count). Two values are returned that are
used as multipliers to incrementally scale
the volume. Some tricky math is used and
is explained below.
RWW 28jun95
*/
static
s16 _getRate(f64 vol, f64 tgt, s32 count, u16* ratel)
{
s16 s;
f64 a;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
if (count == 0){
if (tgt >= vol){
*ratel = 0xffff;
return 0x7fff;
}
else{
*ratel = 0;
return -0x8000;
}
}
a = ((tgt - vol)/(f32)count) * 8.0;
if(a < 0.0)
a = a - 1.0;
s = (s16) a;
*ratel = (s16)(0xffff * (a - (f32) s));
#ifdef AUD_PROFILE
PROFILE_AUD(rate_num, rate_cnt, rate_max, rate_min);
#endif
return (s16)a;
}
static
f32 _getVol(f32 ivol, s32 samples, s16 ratem, u16 ratel)
{
f32 r;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
r = ((f32) (ratem<<16) + (f32) ratel)/65536.0;
ivol += r* samples * 0.125;
#ifdef AUD_PROFILE
PROFILE_AUD(vol_num, vol_cnt, vol_max, vol_min);
#endif
return ivol;
}

View File

@@ -0,0 +1,137 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alEvtqNew(ALEventQueue *evtq, ALEventListItem *items, s32 itemCount)
{
s32 i;
evtq->eventCount = 0;
evtq->allocList.next = 0;
evtq->allocList.prev = 0;
evtq->freeList.next = 0;
evtq->freeList.prev = 0;
if(itemCount > 0){
i = 0;
do{
alLink(&items[i].node, &evtq->freeList);
i++;
} while (i != itemCount);
}
}
ALMicroTime alEvtqNextEvent(ALEventQueue *evtq, ALEvent *evt)
{
ALEventListItem *item;
ALMicroTime delta;
OSIntMask mask;
mask = osSetIntMask(OS_IM_NONE);
item = (ALEventListItem *)evtq->allocList.next;
if (item)
{
alUnlink((ALLink *)item);
alCopy(&item->evt, evt, sizeof(*evt));
alLink((ALLink *)item, &evtq->freeList);
delta = item->delta;
}
else
{
/* sct 11/28/95 - If we get here, most like we overflowed the event queue */
/* with non-self-perpetuating events. Eg. if we filled the evtq with volume */
/* events, then when the seqp is told to play it will handle all the events */
/* at once completely emptying out the queue. At this point this problem */
/* must be treated as an out of resource error and the evtq should be increased. */
evt->type = -1;
delta = 0;
}
osSetIntMask(mask);
return delta;
}
void alEvtqPostEvent(ALEventQueue *evtq, ALEvent *evt, ALMicroTime delta)
{
ALEventListItem *item;
ALEventListItem *nextItem;
ALLink *node;
s32 postAtEnd=0;
OSIntMask mask;
mask = osSetIntMask(OS_IM_NONE);
item = (ALEventListItem *)evtq->freeList.next;
if (!item) {
osSetIntMask(mask);
return;
}
alUnlink(&item->node);
alCopy(evt, &item->evt, sizeof(item->evt));
if (delta == AL_EVTQ_END)
postAtEnd = -1;
for (node = &evtq->allocList; node != 0; node = node->next) {
if (!node->next) { /* end of the list */
if (postAtEnd)
item->delta = 0;
else
item->delta = delta;
alLink(&item->node, node);
break;
} else {
nextItem = (ALEventListItem *)node->next;
if (delta < nextItem->delta) {
item->delta = delta;
nextItem->delta -= delta;
alLink(&item->node, node);
break;
}
delta -= nextItem->delta;
}
}
osSetIntMask(mask);
}
void alEvtqFlushType(ALEventQueue *evtq, s16 type)
{
ALLink *thisNode;
ALLink *nextNode;
ALEventListItem *thisItem, *nextItem;
OSIntMask mask;
mask = osSetIntMask(OS_IM_NONE);
thisNode = evtq->allocList.next;
while( thisNode != 0 )
{
nextNode = thisNode->next;
thisItem = (ALEventListItem *)thisNode;
nextItem = (ALEventListItem *)nextNode;
if (thisItem->evt.type == type)
{
if (nextItem)
nextItem->delta += thisItem->delta;
alUnlink(thisNode);
alLink(thisNode, &evtq->freeList);
}
thisNode = nextNode;
}
osSetIntMask(mask);
}

View File

@@ -0,0 +1,12 @@
#include <ultra64.h>
#include "synthInternals.h"
void alFilterNew(ALFilter *f, ALCmdHandler h, ALSetParam s, s32 type)
{
f->source = 0;
f->handler = h;
f->setParam = s;
f->inp = 0;
f->outp = 0;
f->type = type;
}

View File

@@ -0,0 +1,43 @@
#include <ultra64.h>
#include "synthInternals.h"
void *alHeapDBAlloc(u8 *file, s32 line, ALHeap *hp, s32 num, s32 size)
{
s32 bytes;
u8 *ptr = 0;
bytes = (num*size + AL_CACHE_ALIGN) & ~AL_CACHE_ALIGN;
#ifdef _DEBUG
hp->count++;
bytes += sizeof(HeapInfo);
#endif
if ((hp->cur + bytes) <= (hp->base + hp->len)) {
ptr = hp->cur;
hp->cur += bytes;
#ifdef _DEBUG
((HeapInfo *)ptr)->magic = AL_HEAP_MAGIC;
((HeapInfo *)ptr)->size = bytes;
((HeapInfo *)ptr)->count = hp->count;
if (file) {
((HeapInfo *)ptr)->file = file;
((HeapInfo *)ptr)->line = line;
} else {
((HeapInfo *)ptr)->file = (u8 *) "unknown";
((HeapInfo *)ptr)->line = 0;
}
ptr += sizeof(HeapInfo);
#endif
} else {
#ifdef _DEBUG
__osError(ERR_ALHEAPNOFREE, 1, size);
#endif
}
return ptr;
}

View File

@@ -0,0 +1,16 @@
#include "synthInternals.h"
#include <libaudio.h>
void alHeapInit(ALHeap *hp, u8 *base, s32 len)
{
s32 extraAlign = (AL_CACHE_ALIGN+1) - ((s32) base & AL_CACHE_ALIGN);
if (extraAlign != AL_CACHE_ALIGN+1)
hp->base = base + extraAlign;
else
hp->base = base;
hp->len = len;
hp->cur = hp->base;
hp->count = 0;
}

446
src/core1/done/audio/load.c Normal file
View File

@@ -0,0 +1,446 @@
#include <ultra64.h>
#include "synthInternals.h"
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifdef AUD_PROFILE
extern u32 cnt_index, adpcm_num, adpcm_cnt, adpcm_max, adpcm_min, lastCnt[];
#endif
#define ADPCMFBYTES 9
#define LFSAMPLES 4
static
Acmd *_decodeChunk(Acmd *ptr, ALLoadFilter *f, s32 tsam, s32 nbytes, s16 outp, s16 inp, u32 flags);
Acmd *alAdpcmPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
s16 inp;
s32 tsam;
s32 nframes;
s32 nbytes;
s32 overFlow;
s32 startZero;
s32 nOver;
s32 nSam;
s32 op;
s32 nLeft;
s32 bEnd;
s32 decoded = 0;
s32 looped = 0;
ALLoadFilter *f = (ALLoadFilter *)filter;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
if (outCount == 0)
return ptr;
inp = AL_DECODER_IN;
aLoadADPCM(ptr++, f->bookSize,
K0_TO_PHYS(f->table->waveInfo.adpcmWave.book->book));
looped = (outCount + f->sample > f->loop.end) && (f->loop.count != 0);
if (looped)
nSam = f->loop.end - f->sample;
else
nSam = outCount;
if (f->lastsam)
nLeft = ADPCMFSIZE - f->lastsam;
else
nLeft = 0;
tsam = nSam - nLeft;
if (tsam<0) tsam = 0;
nframes = (tsam+ADPCMFSIZE-1)>>LFSAMPLES;
nbytes = nframes*ADPCMFBYTES;
if (looped){
ptr = _decodeChunk(ptr, f, tsam, nbytes, *outp, inp, f->first);
/*
* Fix up output pointer, which will be used as the input pointer
* by the following module.
*/
if (f->lastsam)
*outp += (f->lastsam<<1);
else
*outp += (ADPCMFSIZE<<1);
/*
* Now fix up state info to reflect the loop start point
*/
f->lastsam = f->loop.start &0xf;
f->memin = (s32) f->table->base + ADPCMFBYTES *
((s32) (f->loop.start>>LFSAMPLES) + 1);
f->sample = f->loop.start;
bEnd = *outp;
while (outCount > nSam){
outCount -= nSam;
/*
* Put next one after the end of the last lot - on the
* frame boundary (32 byte) after the end.
*/
op = (bEnd + ((nframes+1)<<(LFSAMPLES+1))) & ~0x1f;
/*
* The actual end of data
*/
bEnd += (nSam<<1);
/*
* -1 is loop forever - the loop count is not exact now
* for small loops!
*/
if ((f->loop.count != -1) && (f->loop.count != 0))
f->loop.count--;
/*
* What's left to compute.
*/
nSam = MIN(outCount, f->loop.end - f->loop.start);
tsam = nSam - ADPCMFSIZE + f->lastsam;
if (tsam<0) tsam = 0;
nframes = (tsam+ADPCMFSIZE-1)>>LFSAMPLES;
nbytes = nframes*ADPCMFBYTES;
ptr = _decodeChunk(ptr, f, tsam, nbytes, op, inp, f->first | A_LOOP);
/*
* Merge the two sections in DMEM.
*/
aDMEMMove(ptr++, op+(f->lastsam<<1), bEnd, nSam<<1);
}
f->lastsam = (outCount + f->lastsam) & 0xf;
f->sample += outCount;
f->memin += ADPCMFBYTES*nframes;
#ifdef AUD_PROFILE
PROFILE_AUD(adpcm_num, adpcm_cnt, adpcm_max, adpcm_min);
#endif
return ptr;
}
/*
* The unlooped case, which is executed most of the time
*/
nSam = nframes<<LFSAMPLES;
/*
* overFlow is the number of bytes past the end
* of the bitstream I try to generate
*/
overFlow = f->memin + nbytes - ((s32) f->table->base + f->table->len);
if (overFlow < 0)
overFlow = 0;
nOver = (overFlow/ADPCMFBYTES)<<LFSAMPLES;
if (nOver > nSam + nLeft)
nOver = nSam + nLeft;
nbytes -= overFlow;
if ((nOver - (nOver & 0xf))< outCount){
decoded = 1;
ptr = _decodeChunk(ptr, f, nSam - nOver, nbytes, *outp, inp, f->first);
if (f->lastsam)
*outp += (f->lastsam<<1);
else
*outp += (ADPCMFSIZE<<1);
f->lastsam = (outCount + f->lastsam) & 0xf;
f->sample += outCount;
f->memin += ADPCMFBYTES*nframes;
} else {
f->lastsam = 0;
f->memin += ADPCMFBYTES*nframes;
}
/*
* Put zeros in if necessary
*/
if (nOver){
f->lastsam = 0;
if (decoded)
startZero = (nLeft + nSam - nOver)<<1;
else
startZero = 0;
aClearBuffer(ptr++, startZero + *outp, nOver<<1);
}
#ifdef AUD_PROFILE
PROFILE_AUD(adpcm_num, adpcm_cnt, adpcm_max, adpcm_min);
#endif
return ptr;
}
Acmd *alRaw16Pull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
s32 nbytes;
s32 dramLoc;
s32 dramAlign;
s32 dmemAlign;
s32 overFlow;
s32 startZero;
s32 nSam;
s32 op;
ALLoadFilter *f = (ALLoadFilter *)filter;
ALFilter *a = (ALFilter *) filter;
if (outCount == 0)
return ptr;
if ((outCount + f->sample > f->loop.end) && (f->loop.count != 0)){
nSam = f->loop.end - f->sample;
nbytes = nSam<<1;
if (nSam > 0){
dramLoc = (f->dma)(f->memin, nbytes, f->dmaState);
/*
* Make sure enough is loaded into DMEM to take care
* of 8 byte alignment
*/
dramAlign = dramLoc & 0x7;
nbytes += dramAlign;
aSetBuffer(ptr++, 0, *outp, 0, nbytes + 8 - (nbytes & 0x7));
aLoadBuffer(ptr++, dramLoc - dramAlign);
} else
dramAlign = 0;
/*
* Fix up output pointer to allow for dram alignment
*/
*outp += dramAlign;
f->memin = (s32) f->table->base + (f->loop.start<<1);
f->sample = f->loop.start;
op = *outp;
while (outCount > nSam){
op += (nSam<<1);
outCount -= nSam;
/*
* -1 is loop forever
*/
if ((f->loop.count != -1) && (f->loop.count != 0))
f->loop.count--;
/*
* What to compute.
*/
nSam = MIN(outCount, f->loop.end - f->loop.start);
nbytes = nSam<<1;
/*
* Do the next section, same as last.
*/
dramLoc = (f->dma)(f->memin, nbytes, f->dmaState);
/*
* Make sure enough is loaded into DMEM to take care
* of 8 byte alignment
*/
dramAlign = dramLoc & 0x7;
nbytes += dramAlign;
if (op & 0x7)
dmemAlign = 8 - (op & 0x7);
else
dmemAlign = 0;
aSetBuffer(ptr++, 0, op + dmemAlign, 0, nbytes + 8 - (nbytes & 0x7));
aLoadBuffer(ptr++, dramLoc - dramAlign);
/*
* Merge the two sections in DMEM.
*/
if (dramAlign || dmemAlign)
aDMEMMove(ptr++, op+dramAlign+dmemAlign, op, nSam<<1);
}
f->sample += outCount;
f->memin += (outCount<<1);
return ptr;
}
/*
* The unlooped case, which is executed most of the time
*
* overFlow is the number of bytes past the end
* of the bitstream I try to generate
*/
nbytes = outCount<<1;
overFlow = f->memin + nbytes - ((s32) f->table->base + f->table->len);
if (overFlow < 0)
overFlow = 0;
if (overFlow > nbytes)
overFlow = nbytes;
if (overFlow < nbytes){
if (outCount > 0){
nbytes -= overFlow;
dramLoc = (f->dma)(f->memin, nbytes, f->dmaState);
/*
* Make sure enough is loaded into DMEM to take care
* of 8 byte alignment
*/
dramAlign = dramLoc & 0x7;
nbytes += dramAlign;
aSetBuffer(ptr++, 0, *outp, 0, nbytes + 8 - (nbytes & 0x7));
aLoadBuffer(ptr++, dramLoc - dramAlign);
} else
dramAlign = 0;
*outp += dramAlign;
f->sample += outCount;
f->memin += outCount<<1;
} else {
f->memin += outCount<<1;
}
/*
* Put zeros in if necessary
*/
if (overFlow){
startZero = (outCount<<1) - overFlow;
if (startZero < 0)
startZero = 0;
aClearBuffer(ptr++, startZero + *outp, overFlow);
}
return ptr;
}
s32
alLoadParam(void *filter, s32 paramID, void *param)
{
ALLoadFilter *a = (ALLoadFilter *) filter;
ALFilter *f = (ALFilter *) filter;
switch (paramID) {
case (AL_FILTER_SET_WAVETABLE):
a->table = (ALWaveTable *) param;
a->memin = (s32) a->table->base;
a->sample = 0;
switch (a->table->type){
case (AL_ADPCM_WAVE):
/*
* Set up the correct handler
*/
f->handler = alAdpcmPull;
/*
* Make sure the table length is an integer number of
* frames
*/
a->table->len = ADPCMFBYTES *
((s32) (a->table->len/ADPCMFBYTES));
a->bookSize = 2*a->table->waveInfo.adpcmWave.book->order*
a->table->waveInfo.adpcmWave.book->npredictors*ADPCMVSIZE;
if (a->table->waveInfo.adpcmWave.loop) {
a->loop.start = a->table->waveInfo.adpcmWave.loop->start;
a->loop.end = a->table->waveInfo.adpcmWave.loop->end;
a->loop.count = a->table->waveInfo.adpcmWave.loop->count;
alCopy(a->table->waveInfo.adpcmWave.loop->state,
a->lstate, sizeof(ADPCM_STATE));
} else {
a->loop.start = a->loop.end = a->loop.count = 0;
}
break;
case (AL_RAW16_WAVE):
f->handler = alRaw16Pull;
if (a->table->waveInfo.rawWave.loop) {
a->loop.start = a->table->waveInfo.rawWave.loop->start;
a->loop.end = a->table->waveInfo.rawWave.loop->end;
a->loop.count = a->table->waveInfo.rawWave.loop->count;
} else {
a->loop.start = a->loop.end = a->loop.count = 0;
}
break;
default:
break;
}
break;
case (AL_FILTER_RESET):
a->lastsam = 0;
a->first = 1;
a->sample = 0;
/* sct 2/14/96 - Check table since it is initialized to null and */
/* Get loop info according to table type. */
if (a->table)
{
a->memin = (s32) a->table->base;
if (a->table->type == AL_ADPCM_WAVE)
{
if (a->table->waveInfo.adpcmWave.loop)
a->loop.count = a->table->waveInfo.adpcmWave.loop->count;
}
else if (a->table->type == AL_RAW16_WAVE)
{
if (a->table->waveInfo.rawWave.loop)
a->loop.count = a->table->waveInfo.rawWave.loop->count;
}
}
break;
default:
break;
}
}
Acmd *_decodeChunk(Acmd *ptr, ALLoadFilter *f, s32 tsam, s32 nbytes, s16 outp, s16 inp, u32 flags)
{
s32
dramAlign,
dramLoc;
if (nbytes > 0){
dramLoc = (f->dma)(f->memin, nbytes, f->dmaState);
/*
* Make sure enough is loaded into DMEM to take care
* of 8 byte alignment
*/
dramAlign = dramLoc & 0x7;
nbytes += dramAlign;
aSetBuffer(ptr++, 0, inp, 0, nbytes + 8 - (nbytes & 0x7));
aLoadBuffer(ptr++, dramLoc - dramAlign);
} else
dramAlign = 0;
if (flags & A_LOOP){
aSetLoop(ptr++, K0_TO_PHYS(f->lstate));
}
aSetBuffer(ptr++, 0, inp + dramAlign, outp, tsam<<1);
aADPCMdec(ptr++, flags, K0_TO_PHYS(f->state));
f->first = 0;
return ptr;
}

View File

@@ -0,0 +1,46 @@
#include <ultra64.h>
#include "synthInternals.h"
Acmd *alMainBusPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
ALMainBus *m = (ALMainBus *)filter;
ALFilter **sources = m->sources;
s32 i;
/*
* clear the output buffers here
*/
aClearBuffer(ptr++, AL_MAIN_L_OUT, outCount<<1);
aClearBuffer(ptr++, AL_MAIN_R_OUT, outCount<<1);
for (i = 0; i < m->sourceCount; i++) {
ptr = (sources[i]->handler)(sources[i], outp, outCount, sampleOffset,
ptr);
aSetBuffer(ptr++, 0, 0, 0, outCount<<1);
aMix(ptr++, 0, 0x7fff, AL_AUX_L_OUT, AL_MAIN_L_OUT);
aMix(ptr++, 0, 0x7fff, AL_AUX_R_OUT, AL_MAIN_R_OUT);
}
return ptr;
}
s32 alMainBusParam(void *filter, s32 paramID, void *param)
{
ALMainBus *m = (ALMainBus *) filter;
ALFilter **sources = m->sources;
switch (paramID) {
case (AL_FILTER_ADD_SOURCE):
sources[m->sourceCount++] = (ALFilter *) param;
break;
default:
/* ??? */
break;
}
return 0;
}

View File

@@ -0,0 +1,23 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
Acmd *n_alAuxBusPull(s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
N_ALAuxBus *m = (N_ALAuxBus *)n_syn->auxBus;
N_PVoice **sources = m->sources;
s32 i;
#ifndef N_MICRO
aClearBuffer(ptr++, AL_AUX_L_OUT, FIXED_SAMPLE<<1);
aClearBuffer(ptr++, AL_AUX_R_OUT, FIXED_SAMPLE<<1);
#else
aClearBuffer(ptr++, N_AL_AUX_L_OUT, N_AL_DIVIDED<<1);
#endif
for (i = 0; i < m->sourceCount; i++)
ptr = n_alEnvmixerPull(sources[i],sampleOffset,ptr);
return ptr;
}

View File

@@ -0,0 +1,870 @@
#include <ultra64.h>
#include "n_synth.h"
#include <assert.h>
#include "seqp.h"
#include "n_cseqp.h"
#include "cseq.h"
#ifndef assert
#define assert(s)
#endif
static ALMicroTime __n_CSPVoiceHandler(void *node);
static void __n_CSPHandleNextSeqEvent(N_ALCSPlayer *seqp);
static void __n_CSPHandleMIDIMsg(N_ALCSPlayer *seqp, N_ALEvent *event);
static void __n_CSPHandleMetaMsg(N_ALCSPlayer *seqp, N_ALEvent *event);
static void __n_CSPRepostEvent(ALEventQueue *evtq, N_ALEventListItem *item);
static void __n_setUsptFromTempo(N_ALCSPlayer *seqp, ALCSeq *target, f32 tempo); /* sct 1/8/96 */
/*
* Sequence Player public functions
*/
/*done*/
void n_alCSPNew(N_ALCSPlayer *seqp, ALSeqpConfig *c)
{
s32 i;
N_ALEventListItem *items;
N_ALVoiceState *vs;
N_ALVoiceState *voices;
ALHeap *hp = c->heap;
/*
* initialize member variables
*/
seqp->bank = 0;
seqp->target = NULL;
seqp->drvr = n_syn;
seqp->chanMask = 0xffff;
seqp->uspt = 488;
seqp->nextDelta = 0;
seqp->state = AL_STOPPED;
seqp->vol = 0x7FFF; /* full volume */
seqp->debugFlags = c->debugFlags;
seqp->frameTime = AL_USEC_PER_FRAME; /* should get this from driver */
seqp->curTime = 0;
seqp->initOsc = c->initOsc;
seqp->updateOsc = c->updateOsc;
seqp->stopOsc = c->stopOsc;
seqp->nextEvent.type = AL_SEQP_API_EVT; /* this will start the voice handler "spinning" */
/*
* init the channel state
*/
seqp->maxChannels = c->maxChannels;
seqp->chanState = alHeapAlloc(hp, c->maxChannels, sizeof(ALChanState) );
__initChanState((ALSeqPlayer*)seqp); /* sct 11/6/95 */
/*
* init the voice state array
*/
voices = alHeapAlloc(hp, c->maxVoices, sizeof(ALVoiceState));
seqp->vFreeList = 0;
for (i = 0; i < c->maxVoices; i++) {
vs = &voices[i];
vs->next = seqp->vFreeList;
seqp->vFreeList = vs;
}
seqp->vAllocHead = 0;
seqp->vAllocTail = 0;
/*
* init the event queue
*/
items = alHeapAlloc(hp, c->maxEvents, sizeof(ALEventListItem));
alEvtqNew(&seqp->evtq, items, c->maxEvents);
/*
* add ourselves to the driver
*/
seqp->node.next = NULL;
seqp->node.handler = __n_CSPVoiceHandler;
seqp->node.clientData = seqp;
n_alSynAddSeqPlayer(&seqp->node);
}
/*************************************************************
* private routines or driver callback routines
*************************************************************/
static ALMicroTime __n_CSPVoiceHandler(void *node)
{
N_ALCSPlayer *seqp = (N_ALCSPlayer *) node;
N_ALEvent evt;
ALVoice *voice;
ALMicroTime delta;
ALVoiceState *vs;
void *oscState;
f32 oscValue;
u8 chan;
do {
switch (seqp->nextEvent.type)
{
case (AL_SEQ_REF_EVT):
__n_CSPHandleNextSeqEvent(seqp);
break;
case (AL_SEQP_API_EVT):
evt.type = AL_SEQP_API_EVT;
alEvtqPostEvent(&seqp->evtq, (ALEvent *)&evt, seqp->frameTime);
break;
case (AL_NOTE_END_EVT):
voice = seqp->nextEvent.msg.note.voice;
n_alSynStopVoice(voice);
n_alSynFreeVoice(voice);
vs = (ALVoiceState *)voice->clientPrivate;
if(vs->flags)
__seqpStopOsc((ALSeqPlayer*)seqp,vs);
__unmapVoice((ALSeqPlayer*)seqp, voice);
break;
case (AL_SEQP_ENV_EVT):
voice = seqp->nextEvent.msg.vol.voice;
vs = (ALVoiceState *)voice->clientPrivate;
if(vs->envPhase == AL_PHASE_ATTACK)
vs->envPhase = AL_PHASE_DECAY;
delta = seqp->nextEvent.msg.vol.delta;
vs->envEndTime = seqp->curTime + delta;
vs->envGain = seqp->nextEvent.msg.vol.vol;
n_alSynSetVol(voice, __vsVol(vs, (ALSeqPlayer*)seqp), delta);
break;
case (AL_TREM_OSC_EVT):
vs = seqp->nextEvent.msg.osc.vs;
oscState = seqp->nextEvent.msg.osc.oscState;
delta = (*seqp->updateOsc)(oscState,&oscValue);
vs->tremelo = (u8)oscValue;
n_alSynSetVol(&vs->voice, __vsVol(vs,(ALSeqPlayer*)seqp),
__vsDelta(vs,seqp->curTime));
evt.type = AL_TREM_OSC_EVT;
evt.msg.osc.vs = vs;
evt.msg.osc.oscState = oscState;
alEvtqPostEvent(&seqp->evtq, &evt, delta);
break;
case (AL_VIB_OSC_EVT):
vs = seqp->nextEvent.msg.osc.vs;
oscState = seqp->nextEvent.msg.osc.oscState;
chan = seqp->nextEvent.msg.osc.chan;
delta = (*seqp->updateOsc)(oscState,&oscValue);
vs->vibrato = oscValue;
n_alSynSetPitch(&vs->voice, vs->pitch * vs->vibrato
* seqp->chanState[chan].pitchBend);
evt.type = AL_VIB_OSC_EVT;
evt.msg.osc.vs = vs;
evt.msg.osc.oscState = oscState;
evt.msg.osc.chan = chan;
alEvtqPostEvent(&seqp->evtq, &evt, delta);
break;
case (AL_SEQP_MIDI_EVT):
case (AL_CSP_NOTEOFF_EVT): /* nextEvent is a note off midi message */
__n_CSPHandleMIDIMsg(seqp, &seqp->nextEvent);
break;
case (AL_SEQP_META_EVT):
__n_CSPHandleMetaMsg(seqp, &seqp->nextEvent);
break;
case (AL_SEQP_VOL_EVT):
seqp->vol = seqp->nextEvent.msg.spvol.vol;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
n_alSynSetVol(&vs->voice,
__vsVol(vs, (ALSeqPlayer*)seqp),
__vsDelta(vs, seqp->curTime));
}
break;
case (AL_SEQP_PLAY_EVT):
if (seqp->state != AL_PLAYING)
{
seqp->state = AL_PLAYING;
func_80250650();
__n_CSPPostNextSeqEvent(seqp); /* seqp must be AL_PLAYING before we call this routine. */
}
break;
case (AL_SEQP_STOP_EVT):
if ( seqp->state == AL_STOPPING )
{
for (vs = seqp->vAllocHead; vs != 0; vs = seqp->vAllocHead)
{
#ifdef _DEBUG
__osError(ERR_ALCSPVNOTFREE, 2, vs->channel, vs->key);
#endif
n_alSynStopVoice(&vs->voice);
n_alSynFreeVoice(&vs->voice);
if(vs->flags)
__seqpStopOsc((ALSeqPlayer*)seqp,vs);
__unmapVoice((ALSeqPlayer*)seqp, &vs->voice);
}
seqp->state = AL_STOPPED;
/* alEvtqFlush(&seqp->evtq); - Don't flush event queue
anymore. */
/* sct 1/3/96 - Don't overwrite nextEvent with
AL_SEQP_API_EVT or set nextDelta to
AL_USEC_PER_FRAME since we're not stopping event
processing. */
/* sct 1/3/96 - Don't return here since we keep
processing events as usual. */
}
break;
case (AL_SEQP_STOPPING_EVT):
if (seqp->state == AL_PLAYING)
{
/* sct 12/29/95 - Remove events associated with the
* stopping sequence. For compact sequence player,
* also remove all queued note off events since they
* are not contained in a compact sequence but are
* generated in response to note ons. Note that
* flushing AL_SEQP_MIDI_EVTs may flush events that
* were posted after the call to alSeqpStop, so the
* application must queue these events either when
* the player is fully stopped, or when it is
* playing. */
alEvtqFlushType(&seqp->evtq, AL_SEQ_REF_EVT);
alEvtqFlushType(&seqp->evtq, AL_CSP_NOTEOFF_EVT);
alEvtqFlushType(&seqp->evtq, AL_SEQP_MIDI_EVT);
/* sct 1/3/96 - Check to see which voices need to be
killed and release them. */
/* Unkilled voices should have note end events
occurring prior to KILL_TIME. */
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if (__voiceNeedsNoteKill ((ALSeqPlayer*)seqp, &vs->voice, KILL_TIME))
__seqpReleaseVoice((ALSeqPlayer*)seqp, &vs->voice, KILL_TIME);
}
seqp->state = AL_STOPPING;
evt.type = AL_SEQP_STOP_EVT;
alEvtqPostEvent(&seqp->evtq, &evt, AL_EVTQ_END);
}
break;
case (AL_SEQP_PRIORITY_EVT):
chan = seqp->nextEvent.msg.sppriority.chan;
seqp->chanState[chan].priority = seqp->nextEvent.msg.sppriority.priority;
break;
case (AL_SEQP_SEQ_EVT):
//assert(seqp->state != AL_PLAYING); /* Must be done playing to change sequences. */
((seqp->state != AL_PLAYING)?((void)0):func_8033F000("seqp->state != AL_PLAYING","n_csplayer.c", 272));
seqp->target = seqp->nextEvent.msg.spseq.seq;
seqp->chanMask = 0xFFFF;
if (seqp->bank)
__initFromBank((ALSeqPlayer *)seqp, seqp->bank);
break;
case (AL_SEQP_BANK_EVT):
//assert(seqp->state == AL_STOPPED); /* Must be fully stopped to change banks. */
((seqp->state == AL_STOPPED)?((void)0):func_8033F000("seqp->state == AL_STOPPED","n_csplayer.c", 283));
seqp->bank = seqp->nextEvent.msg.spbank.bank;
__initFromBank((ALSeqPlayer *)seqp, seqp->bank);
break;
/* sct 11/6/95 - these events should now be handled by __n_CSPHandleNextSeqEvent */
case (AL_SEQ_END_EVT):
case (AL_TEMPO_EVT):
case (AL_SEQ_MIDI_EVT):
//assert(FALSE);
((FALSE)?((void)0):func_8033F000("FALSE","n_csplayer.c", 296));
break;
}
seqp->nextDelta = alEvtqNextEvent(&seqp->evtq, &seqp->nextEvent);
} while (seqp->nextDelta == 0);
/*
* assume that next callback won't be more than half an
* hour away
*/
seqp->curTime += seqp->nextDelta; /* sct 11/7/95 */
return seqp->nextDelta;
}
/*
Calculates the delta time in ticks until the next sequence
event and posts a sequence reference event with the time in usecs.
Loops are handled automatically by the compact sequence.
Does nothing if the sequence player is not playing or if there
is no target sequence.
sct 11/7/95
*/
/*DONE*/
void __n_CSPPostNextSeqEvent(N_ALCSPlayer *seqp)
{
ALEvent evt;
s32 deltaTicks;
if (seqp->state != AL_PLAYING || seqp->target == NULL)
return;
/* Get the next event time in ticks. */
/* If false is returned, then there is no next delta (ie. end of sequence reached). */
if (!__alCSeqNextDelta(seqp->target, &deltaTicks))
return;
evt.type = AL_SEQ_REF_EVT;
alEvtqPostEvent(&seqp->evtq, &evt, deltaTicks * seqp->uspt);
}
/*
Call this routine to handle the next event in the sequence.
Assumes that the next sequence event is scheduled to be processed
immediately since it does not check the event's tick time.
sct 11/7/95
*/
static void
__n_CSPHandleNextSeqEvent(N_ALCSPlayer *seqp)
{
ALEvent evt;
/* sct 1/5/96 - Do nothing if we don't have a target sequence. */
if (seqp->target == NULL)
return;
alCSeqNextEvent(seqp->target, &evt);
switch (evt.type)
{
case AL_SEQ_MIDI_EVT:
__n_CSPHandleMIDIMsg(seqp, &evt);
__n_CSPPostNextSeqEvent(seqp);
break;
case AL_TEMPO_EVT:
__n_CSPHandleMetaMsg(seqp, &evt);
__n_CSPPostNextSeqEvent(seqp);
break;
case AL_SEQ_END_EVT:
seqp->state = AL_STOPPING;
evt.type = AL_SEQP_STOP_EVT;
alEvtqPostEvent(&seqp->evtq, &evt, AL_EVTQ_END);
break;
case AL_TRACK_END:
case AL_CSP_LOOPSTART:
case AL_CSP_LOOPEND:
__n_CSPPostNextSeqEvent(seqp);
break;
default:
//assert(FALSE); /* Sequence event type not supported. */
((FALSE)?((void)0):func_8033F000("FALSE","n_csplayer.c", 353));
break;
}
}
static void __n_CSPHandleMIDIMsg(N_ALCSPlayer *seqp, N_ALEvent *event)
{
N_ALVoice *voice;
N_ALVoiceState *vs;
s32 status;
u8 chan;
u8 key;
u8 vel;
u8 byte1;
u8 byte2;
ALMIDIEvent *midi = &event->msg.midi;
s16 vol;
N_ALEvent evt;
ALMicroTime deltaTime;
N_ALVoiceState *vstate;
ALPan pan;
ALFxRef fxref;
status = midi->status & AL_MIDI_StatusMask;
chan = midi->status & AL_MIDI_ChannelMask;
byte1 = key = midi->byte1;
byte2 = vel = midi->byte2;
if(status == AL_MIDI_ChannelModeSelect){
if(byte1 == 0x7E){
seqp->chanMask &= ~(1 << byte2);
vstate = seqp->vAllocHead;
while(vs){
if(vstate->channel == byte2){
__seqpReleaseVoice(seqp, &vstate->voice.node.next, vstate->sound->envelope->releaseTime);
}
vs = vs->next;
}
return;
}else if(byte1 == 0x7F){
seqp->chanMask |= (1 << byte2);
return;
}
}
if(!((seqp->chanMask & (1 << chan)) || status != AL_MIDI_NoteOn))
return;
//L8025DB08
switch (status)
{
case (AL_MIDI_NoteOn):
if (vel != 0) /* a real note on */
{
ALVoiceConfig config;
ALSound *sound;
s16 cents;
f32 pitch,oscValue;
u8 fxmix;
void *oscState;
ALInstrument *inst;
/* If we're not playing, don't process note ons. */
if (seqp->state != AL_PLAYING)
break;
sound = __lookupSoundQuick((ALSeqPlayer*)seqp, key, vel, chan);
ALFlagFailIf(!sound, seqp->debugFlags & NO_SOUND_ERR_MASK,
ERR_ALSEQP_NO_SOUND);
config.priority = seqp->chanState[chan].priority;
config.fxBus = 0;
config.unityPitch = 0;
vstate = __mapVoice((ALSeqPlayer*)seqp, key, vel, chan);
ALFlagFailIf(!vstate, seqp->debugFlags & NO_VOICE_ERR_MASK,
ERR_ALSEQP_NO_VOICE );
voice = &vstate->voice;
n_alSynAllocVoice(voice, &config);
/*
* set up the voice state structure
*/
vstate->sound = sound;
vstate->envPhase = AL_PHASE_ATTACK;
if (seqp->chanState[chan].sustain > AL_SUSTAIN)
vstate->phase = AL_PHASE_SUSTAIN;
else
vstate->phase = AL_PHASE_NOTEON;
cents = (key - sound->keyMap->keyBase) * 100
+ sound->keyMap->detune;
vstate->pitch = alCents2Ratio(cents);
vstate->envGain = sound->envelope->attackVolume;
vstate->envEndTime = seqp->curTime +
sound->envelope->attackTime;
/*
* setup tremelo and vibrato if active
*/
vstate->flags = 0;
inst = seqp->chanState[chan].instrument;
oscValue = (f32)AL_VOL_FULL; /* set this as a default */
if(inst->tremType)
{
if(seqp->initOsc)
{
deltaTime = (*seqp->initOsc)(&oscState,&oscValue,inst->tremType,
inst->tremRate,inst->tremDepth,inst->tremDelay);
if(deltaTime) /* a deltaTime of zero means don't run osc */
{
evt.type = AL_TREM_OSC_EVT;
evt.msg.osc.vs = vstate;
evt.msg.osc.oscState = oscState;
alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
vstate->flags |= 0x01; /* set tremelo flag bit */
}
}
}
vstate->tremelo = (u8)oscValue; /* will default if not changed by initOsc */
oscValue = 1.0f; /* set this as a default */
if(inst->vibType)
{
if(seqp->initOsc)
{
deltaTime = (*seqp->initOsc)(&oscState,&oscValue,inst->vibType,
inst->vibRate,inst->vibDepth,inst->vibDelay);
if(deltaTime) /* a deltaTime of zero means don't run osc. */
{
evt.type = AL_VIB_OSC_EVT;
evt.msg.osc.vs = vstate;
evt.msg.osc.oscState = oscState;
evt.msg.osc.chan = chan;
alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
vstate->flags |= 0x02; /* set the vibrato flag bit */
}
}
}
vstate->vibrato = oscValue; /* will default if not changed by initOsc */
/*
* calculate the note on parameters
*/
pitch = vstate->pitch * seqp->chanState[chan].pitchBend *
vstate->vibrato;
fxmix = seqp->chanState[chan].fxmix;
pan = __vsPan(vstate, (ALSeqPlayer*)seqp);
vol = __vsVol(vstate, (ALSeqPlayer*)seqp);
deltaTime = sound->envelope->attackTime;
n_alSynStartVoiceParams(voice, sound->wavetable,
pitch, vol, pan, fxmix, deltaTime);
/*
* set up callbacks for envelope
*/
evt.type = AL_SEQP_ENV_EVT;
evt.msg.vol.voice = voice;
evt.msg.vol.vol = sound->envelope->decayVolume;
evt.msg.vol.delta = sound->envelope->decayTime;
alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
if(midi->duration)
{
/*
* set up note off evt. if no duration don't do this
*/
evt.type = AL_CSP_NOTEOFF_EVT;
evt.msg.midi.status = chan | AL_MIDI_NoteOff;
evt.msg.midi.byte1 = key;
evt.msg.midi.byte2 = 0; /* not needed ? */
deltaTime = seqp->uspt * midi->duration;
/* max time would be about one hour ten minutes */
alEvtqPostEvent(&seqp->evtq, &evt, deltaTime);
}
break;
}
/*
* NOTE: intentional fall-through for note on with zero
* velocity (Should never happen with compact midi sequence,
* but could happen with real time midi.)
*/
case (AL_MIDI_NoteOff):
vstate = __lookupVoice((ALSeqPlayer*)seqp, key, chan);
ALFlagFailIf(!vstate, seqp->debugFlags & NOTE_OFF_ERR_MASK,
ERR_ALSEQP_OFF_VOICE );
if (vstate->phase == AL_PHASE_SUSTAIN)
vstate->phase = AL_PHASE_SUSTREL;
else
{
vstate->phase = AL_PHASE_RELEASE;
__seqpReleaseVoice((ALSeqPlayer*)seqp, &vstate->voice,
vstate->sound->envelope->releaseTime);
}
break;
case (AL_MIDI_PolyKeyPressure):
/*
* Aftertouch per key (hardwired to volume). Note that
* aftertouch affects only notes that are already
* sounding.
*/
vstate = __lookupVoice((ALSeqPlayer*)seqp, key, chan);
ALFailIf(!vstate, ERR_ALSEQP_POLY_VOICE );
vstate->velocity = byte2;
n_alSynSetVol(&vstate->voice,
__vsVol(vstate, (ALSeqPlayer*)seqp),
__vsDelta(vstate,seqp->curTime));
break;
case (AL_MIDI_ChannelPressure):
/*
* Aftertouch per channel (hardwired to volume). Note that
* aftertouch affects only notes that are already
* sounding.
*/
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) {
if (vs->channel == chan) {
vs->velocity = byte1;
n_alSynSetVol(&vs->voice,
__vsVol(vs, (ALSeqPlayer*)seqp),
__vsDelta(vs,seqp->curTime));
}
}
break;
case (AL_MIDI_ControlChange):
switch (byte1)
{
case (AL_MIDI_PAN_CTRL):
seqp->chanState[chan].pan = byte2;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if (vs->channel == chan)
{
pan = __vsPan(vs, (ALSeqPlayer*)seqp);
n_alSynSetPan(&vs->voice, pan);
}
}
break;
case (AL_MIDI_VOLUME_CTRL):
seqp->chanState[chan].vol = byte2;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if ((vs->channel == chan) && (vs->envPhase != AL_PHASE_RELEASE))
{
vol = __vsVol(vs, (ALSeqPlayer*)seqp);
n_alSynSetVol(&vs->voice, vol,
__vsDelta(vs,seqp->curTime));
}
}
break;
case (0x7D):
seqp->chanState[chan].unk9 = byte2;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if ((vs->channel == chan) && (vs->envPhase != AL_PHASE_RELEASE))
{
vol = __vsVol(vs, (ALSeqPlayer*)seqp);
n_alSynSetVol(&vs->voice, vol,
__vsDelta(vs,seqp->curTime));
}
}
break;
case (AL_MIDI_PRIORITY_CTRL):
/* leave current voices where they are */
seqp->chanState[chan].priority = byte2;
break;
case (AL_MIDI_SUSTAIN_CTRL):
seqp->chanState[chan].sustain = byte2;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if ((vs->channel == chan) && (vs->phase != AL_PHASE_RELEASE))
{
if ( byte2 > AL_SUSTAIN )
{
/*
* sustain pedal down
*/
if (vs->phase == AL_PHASE_NOTEON)
vs->phase = AL_PHASE_SUSTAIN;
}
else
{
/*
* sustain pedal up
*/
if (vs->phase == AL_PHASE_SUSTAIN)
vs->phase = AL_PHASE_NOTEON;
else if(vs->phase == AL_PHASE_SUSTREL)
{
vs->phase = AL_PHASE_RELEASE;
__seqpReleaseVoice((ALSeqPlayer*)seqp,
&vs->voice,
vs->sound->envelope->releaseTime);
}
}
}
}
break;
case (AL_MIDI_FX1_CTRL):
seqp->chanState[chan].fxmix = byte2;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
{
if (vs->channel == chan)
n_alSynSetFXMix(&vs->voice, byte2);
}
break;
case (0x6A):
case (0x6B):
case (0x6C):
case (0x6D):
case (0x6E):
case (0x6F):
case (0x70):
case (0x71):
case (0x72):
case (0x73):
case (0x74):
case (0x75):
case (0x76):
case (0x77):
func_80250104(seqp->target,key, chan);
break;
default:
break;
}
break;
case (AL_MIDI_ProgramChange):
/* sct 1/16/96 - We must have a valid bank in order to process the program change. */
//assert(seqp->bank != NULL);
((seqp->bank != NULL)?((void)0):func_8033F000("seqp->bank != NULL", "n_csplayer.c", 715));
if (key < seqp->bank->instCount)
{
ALInstrument *inst = seqp->bank->instArray[key];
__setInstChanState((ALSeqPlayer*)seqp, inst, chan); /* sct 11/6/95 */
}
else
{
#ifdef _DEBUG
__osError(ERR_ALSEQPINVALIDPROG, 2, key, seqp->bank->instCount);
#endif
}
break;
case (AL_MIDI_PitchBendChange):
{
s32 bendVal;
f32 bendRatio;
s32 cents;
/* get 14-bit unsigned midi value */
bendVal = ( (byte2 << 7) + byte1) - 8192;
/* calculate pitch bend in cents */
cents = (seqp->chanState[chan].bendRange * bendVal)/8192;
/* calculate the corresponding ratio */
bendRatio = alCents2Ratio(cents);
seqp->chanState[chan].pitchBend = bendRatio;
for (vs = seqp->vAllocHead; vs != 0; vs = vs->next)
if (vs->channel == chan)
n_alSynSetPitch(&vs->voice,
vs->pitch * bendRatio * vs->vibrato);
}
break;
default:
#ifdef _DEBUG
__osError(ERR_ALSEQPUNKNOWNMIDI, 1, status);
#endif
break;
}
}
/*Done*/
static void __n_CSPHandleMetaMsg(N_ALCSPlayer *seqp, N_ALEvent *event)
{
ALTempoEvent *tevt = &event->msg.tempo;
ALEvent evt;
s32 tempo;
s32 oldUspt;
u32 ticks;
ALMicroTime tempDelta,curDelta = 0;
ALEventListItem *thisNode,*nextNode,*firstTemp = 0;
if (event->msg.tempo.status == AL_MIDI_Meta)
{
if (event->msg.tempo.type == AL_MIDI_META_TEMPO)
{
oldUspt = seqp->uspt;
tempo = (tevt->byte1 << 16) | (tevt->byte2 << 8) | (tevt->byte3 << 0);
__n_setUsptFromTempo (seqp, seqp->target, (f32)tempo); /* sct 1/8/96 */
thisNode = (ALEventListItem*)seqp->evtq.allocList.next;
while(thisNode)
{
curDelta += thisNode->delta;
nextNode = (ALEventListItem*)thisNode->node.next;
if(thisNode->evt.type == AL_CSP_NOTEOFF_EVT)
{
alUnlink((ALLink*)thisNode);
if(firstTemp)
alLink((ALLink*)thisNode,(ALLink*)firstTemp);
else
{
thisNode->node.next = 0;
thisNode->node.prev = 0;
firstTemp = thisNode;
}
tempDelta = curDelta; /* record the current delta */
if(nextNode) /* don't do this if no nextNode */
{
curDelta -= thisNode->delta; /* subtract out this delta */
nextNode->delta += thisNode->delta; /* add it to next event */
}
thisNode->delta = tempDelta; /* set this event delta from current */
}
thisNode = nextNode;
}
thisNode = firstTemp;
while(thisNode)
{
nextNode = (ALEventListItem*)thisNode->node.next;
ticks = thisNode->delta/oldUspt;
thisNode->delta = ticks * seqp->uspt;
__n_CSPRepostEvent(&seqp->evtq,thisNode);
thisNode = nextNode;
}
}
}
}
/*Done*/
static void __n_CSPRepostEvent(ALEventQueue *evtq, N_ALEventListItem *item)
{
OSIntMask mask;
ALLink *node;
N_ALEventListItem *nextItem;
mask = osSetIntMask(OS_IM_NONE);
for (node = &evtq->allocList; node != 0; node = node->next)
{
if (!node->next) /* end of the list */
{
alLink((ALLink *)item, node);
break;
}
else
{
nextItem = (N_ALEventListItem *)node->next;
if (item->delta < nextItem->delta)
{
nextItem->delta -= item->delta;
alLink((ALLink *)item, node);
break;
}
item->delta -= nextItem->delta;
}
}
osSetIntMask(mask);
}
/*
This routine safely calculates the sequence player's
uspt value based on the given tempo. It does this safely
by making sure that the player has a target sequence and
therefore a qnpt value which is needed for the calculation.
Compact sequence player needs its own version of this routine
since the ALCSeq's qnpt field is at a different offset.
*/
/* DONE */
static void __n_setUsptFromTempo(N_ALCSPlayer *seqp, ALCSeq *target, f32 tempo)
{
if (target)
seqp->uspt = (s32)((f32)tempo * target->qnpt);
else
seqp->uspt = 488; /* This is the initial value set by alSeqpNew. */
}

View File

@@ -0,0 +1,292 @@
#include <ultra64.h>
#include "n_libaudio.h"
static u32 __readVarLen(ALCSeq *s,u32 track);
static u8 __getTrackByte(ALCSeq *s,u32 track);
static u32 __n_alCSeqGetTrackEvent(ALCSeq *seq, u32 track, N_ALEvent *event);
void n_alCSeqNew(ALCSeq *seq, u8 *ptr)
{
u32 i,tmpOff,flagTmp;
/* load the seqence pointed to by ptr */
seq->base = (ALCMidiHdr*)ptr;
seq->validTracks = 0;
seq->lastDeltaTicks = 0;
seq->lastTicks = 0;
seq->deltaFlag = 1;
for(i = 0; i < 16; i++)
{
seq->lastStatus[i] = 0;
seq->curBUPtr[i] = 0;
seq->curBULen[i] = 0;
tmpOff = seq->base->trackOffset[i];
if(tmpOff) /* if the track is valid */
{
flagTmp = 1 << i;
seq->validTracks |= flagTmp;
seq->curLoc[i] = (u8*)((u32)ptr + tmpOff);
seq->evtDeltaTicks[i] = __readVarLen(seq,i);
/*__n_alCSeqGetTrackEvent(seq,i); prime the event buffers */
}
else
seq->curLoc[i] = 0;
}
seq->qnpt = 1.0/(f32)seq->base->division;
}
void n_alCSeqNextEvent(ALCSeq *seq,N_ALEvent *evt)
{
u32 i;
u32 firstTime = 0xFFFFFFFF;
u32 firstTrack;
u32 lastTicks = seq->lastDeltaTicks;
#ifdef _DEBUG
/* sct 1/17/96 - Warn if we are beyond the end of sequence. */
if (!seq->validTracks)
__osError(ERR_ALSEQOVERRUN, 0);
#endif
for(i = 0; i < 16 ; i++)
{
if((seq->validTracks >> i) & 1)
{
if(seq->deltaFlag)
seq->evtDeltaTicks[i] -= lastTicks;
if(seq->evtDeltaTicks[i] < firstTime)
{
firstTime = seq->evtDeltaTicks[i];
firstTrack = i;
}
}
}
__n_alCSeqGetTrackEvent(seq,firstTrack,evt);
evt->msg.midi.ticks = firstTime;
seq->lastTicks += firstTime;
seq->lastDeltaTicks = firstTime;
if(evt->type != AL_TRACK_END)
seq->evtDeltaTicks[firstTrack] += __readVarLen(seq,firstTrack);
seq->deltaFlag = 1;
}
/* only call n_alCSeqGetTrackEvent with a valid track !! */
static u32 __n_alCSeqGetTrackEvent(ALCSeq *seq, u32 track, N_ALEvent *event)
{
u32 offset;
u8 status, loopCt, curLpCt, *tmpPtr;
status = __getTrackByte(seq,track); /* read the status byte */
if (status == AL_MIDI_Meta) /* running status not allowed on meta events!! */
{
u8 type = __getTrackByte(seq,track);
if (type == AL_MIDI_META_TEMPO)
{
event->type = AL_TEMPO_EVT;
event->msg.tempo.status = status;
event->msg.tempo.type = type;
event->msg.tempo.byte1 = __getTrackByte(seq,track);
event->msg.tempo.byte2 = __getTrackByte(seq,track);
event->msg.tempo.byte3 = __getTrackByte(seq,track);
seq->lastStatus[track] = 0; /* lastStatus not supported after meta */
}
else if (type == AL_MIDI_META_EOT)
{
u32 flagMask;
flagMask = 0x01 << track;
seq->validTracks = seq->validTracks ^ flagMask;
if(seq->validTracks) /* there is music left don't end */
event->type = AL_TRACK_END;
else /* no more music send AL_SEQ_END_EVT msg */
event->type = AL_SEQ_END_EVT;
}
else if (type == AL_CMIDI_LOOPSTART_CODE)
{
status = __getTrackByte(seq,track); /* get next two bytes, ignore them */
status = __getTrackByte(seq,track);
seq->lastStatus[track] = 0;
event->type = AL_CSP_LOOPSTART;
}
else if (type == AL_CMIDI_LOOPEND_CODE)
{
tmpPtr = seq->curLoc[track];
loopCt = *tmpPtr++;
curLpCt = *tmpPtr;
if(curLpCt == 0) /* done looping */
{
*tmpPtr = loopCt; /* reset current loop count */
seq->curLoc[track] = tmpPtr + 5; /* move pointer to end of event */
}
else
{
if(curLpCt != 0xFF) /* not a loop forever */
*tmpPtr = curLpCt - 1; /* decrement current loop count */
tmpPtr++; /* get offset from end of event */
offset = (*tmpPtr++) << 24;
offset += (*tmpPtr++) << 16;
offset += (*tmpPtr++) << 8;
offset += *tmpPtr++;
seq->curLoc[track] = tmpPtr - offset;
}
seq->lastStatus[track] = 0;
event->type = AL_CSP_LOOPEND;
}
#ifdef _DEBUG
else
__osError(ERR_ALSEQMETA, 1, type);
#endif
}
else
{
event->type = AL_SEQ_MIDI_EVT;
if (status & 0x80) /* if high bit is set, then new status */
{
event->msg.midi.status = status;
event->msg.midi.byte1 = __getTrackByte(seq,track);
seq->lastStatus[track] = status;
}
else /* running status */
{
#ifdef _DEBUG
if(seq->lastStatus[track] == 0)
__osError(ERR_ALCSEQZEROSTATUS, 1, track);
#endif
event->msg.midi.status = seq->lastStatus[track];
event->msg.midi.byte1 = status;
}
if (((event->msg.midi.status & 0xf0) != AL_MIDI_ProgramChange) &&
((event->msg.midi.status & 0xf0) != AL_MIDI_ChannelPressure))
{
event->msg.midi.byte2 = __getTrackByte(seq,track);
if((event->msg.midi.status & 0xf0) == AL_MIDI_NoteOn)
{
event->msg.midi.duration = __readVarLen(seq,track);
#ifdef _DEBUG
if(event->msg.midi.byte2 == 0)
__osError( ERR_ALCSEQZEROVEL, 1, track);
#endif
}
}
else
event->msg.midi.byte2 = 0;
}
return TRUE;
}
void n_alCSeqNewMarker(ALCSeq *seq, ALCSeqMarker *m, u32 ticks)
{
N_ALEvent evt;
ALCSeq tempSeq;
s32 i;
n_alCSeqNew(&tempSeq, (u8*)seq->base);
do {
m->validTracks = tempSeq.validTracks;
m->lastTicks = tempSeq.lastTicks;
m->lastDeltaTicks = tempSeq.lastDeltaTicks;
for(i=0;i<16;i++)
{
m->curLoc[i] = tempSeq.curLoc[i];
m->curBUPtr[i] = tempSeq.curBUPtr[i];
m->curBULen[i] = tempSeq.curBULen[i];
m->lastStatus[i] = tempSeq.lastStatus[i];
m->evtDeltaTicks[i] = tempSeq.evtDeltaTicks[i];
}
n_alCSeqNextEvent(&tempSeq, &evt);
if (evt.type == AL_SEQ_END_EVT)
break;
} while (tempSeq.lastTicks < ticks);
}
/* non-aligned byte reading routines */
static u8 __getTrackByte(ALCSeq *seq,u32 track)
{
u8 theByte;
if(seq->curBULen[track])
{
theByte = *seq->curBUPtr[track];
seq->curBUPtr[track]++;
seq->curBULen[track]--;
}
else /* need to handle backup mode */
{
theByte = *seq->curLoc[track];
seq->curLoc[track]++;
if(theByte == AL_CMIDI_BLOCK_CODE)
{
u8 loBackUp,hiBackUp,theLen,nextByte;
u32 backup;
nextByte = *seq->curLoc[track];
seq->curLoc[track]++;
if(nextByte != AL_CMIDI_BLOCK_CODE)
{
/* if here, then got a backup section. get the amount of
backup, and the len of the section. Subtract the amount of
backup from the curLoc ptr, and subtract four more, since
curLoc has been advanced by four while reading the codes. */
hiBackUp = nextByte;
loBackUp = *seq->curLoc[track];
seq->curLoc[track]++;
theLen = *seq->curLoc[track];
seq->curLoc[track]++;
backup = (u32)hiBackUp;
backup = backup << 8;
backup += loBackUp;
seq->curBUPtr[track] = seq->curLoc[track] - (backup + 4);
seq->curBULen[track] = (u32)theLen;
/* now get the byte */
theByte = *seq->curBUPtr[track];
seq->curBUPtr[track]++;
seq->curBULen[track]--;
}
}
}
return theByte;
}
static u32 __readVarLen(ALCSeq *seq,u32 track)
{
u32 value;
u32 c;
value = (u32)__getTrackByte(seq,track);
if ( value & 0x00000080 )
{
value &= 0x7f;
do
{
c = (u32)__getTrackByte(seq,track);
value = (value << 7) + (c & 0x7f);
} while (c & 0x80);
}
return (value);
}

View File

@@ -0,0 +1,188 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
/*
* WARNING: THE FOLLOWING CONSTANT MUST BE KEPT IN SYNC
* WITH SCALING IN MICROCODE!!!
*/
#define SCALE 16384
/*
* the following arrays contain default parameters for
* a few hopefully useful effects.
*/
#define ms *(((s32)((f32)44.1))&~0x7)
s32 SMALLROOM_PARAMS_N[26] = {
/* sections length */
3, 100 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 54 ms, 9830, -9830, 0, 0, 0, 0,
19 ms, 38 ms, 3276, -3276, 0x3fff, 0, 0, 0,
0, 60 ms, 5000, 0, 0, 0, 0, 0x5000
};
s32 BIGROOM_PARAMS_N[34] = {
/* sections length */
4, 100 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 66 ms, 9830, -9830, 0, 0, 0, 0,
22 ms, 54 ms, 3276, -3276, 0x3fff, 0, 0, 0,
66 ms, 91 ms, 3276, -3276, 0x3fff, 0, 0, 0,
0, 94 ms, 8000, 0, 0, 0, 0, 0x5000
};
s32 ECHO_PARAMS_N[10] = {
/* sections length */
1, 200 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 179 ms, 12000, 0, 0x7fff, 0, 0, 0
};
s32 CHORUS_PARAMS_N[10] = {
/* sections length */
1, 20 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 5 ms, 0x4000, 0, 0x7fff, 7600, 700, 0
};
s32 FLANGE_PARAMS_N[10] = {
/* sections length */
1, 20 ms,
/* chorus chorus filter
input output fbcoef ffcoef gain rate depth coef */
0, 5 ms, 0, 0x5fff, 0x7fff, 380, 500, 0
};
s32 NULL_PARAMS_N[10] = {
0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
void n_alFxNew(ALFx **fx_ar, ALSynConfig *c, ALHeap *hp)
{
u16 i, j, k;
s32 *param = 0;
ALDelay *d;
ALFx *r;
*fx_ar = r = (ALFx *)alHeapAlloc(hp, 1, sizeof(ALFx));
switch (c->fxType) {
case AL_FX_SMALLROOM: param = SMALLROOM_PARAMS_N; break;
case AL_FX_BIGROOM: param = BIGROOM_PARAMS_N; break;
case AL_FX_ECHO: param = ECHO_PARAMS_N; break;
case AL_FX_CHORUS: param = CHORUS_PARAMS_N; break;
case AL_FX_FLANGE: param = FLANGE_PARAMS_N; break;
case AL_FX_CUSTOM: param = c->params; break;
default: param = NULL_PARAMS_N; break;
}
j = 0;
r->section_count = param[j++];
r->length = param[j++];
r->delay = alHeapAlloc(hp, r->section_count, sizeof(ALDelay));
r->base = alHeapAlloc(hp, r->length, sizeof(s16));
r->input = r->base;
for ( k=0; k < r->length; k++)
r->base[k] = 0;
for ( i=0; i<r->section_count; i++ ){
d = &r->delay[i];
d->input = param[j++];
d->output = param[j++];
d->fbcoef = param[j++];
d->ffcoef = param[j++];
d->gain = param[j++];
if (param[j]) {
#define RANGE 2.0
/* d->rsinc = ((f32) param[j++])/0xffffff; */
d->rsinc = ((((f32)param[j++])/1000) * RANGE)/c->outputRate;
/*
* the following constant is derived from:
*
* ratio = 2^(cents/1200)
*
* and therefore for hundredths of a cent
* x
* ln(ratio) = ---------------
* (120,000)/ln(2)
* where
* 120,000/ln(2) = 173123.40...
*/
#define CONVERT 173123.404906676
#define LENGTH (d->output - d->input)
d->rsgain = (((f32) param[j++])/CONVERT) * LENGTH;
d->rsval = 1.0;
d->rsdelta = 0.0;
d->rs = alHeapAlloc(hp, 1, sizeof(ALResampler));
d->rs->state = alHeapAlloc(hp, 1, sizeof(RESAMPLE_STATE));
d->rs->delta = 0.0;
d->rs->first = 1;
} else {
d->rs = 0;
j++;
j++;
}
if (param[j]) {
d->lp = alHeapAlloc(hp, 1, sizeof(ALLowPass));
d->lp->fstate = alHeapAlloc(hp, 1, sizeof(POLEF_STATE));
d->lp->fc = param[j++];
_init_lpfilter(d->lp);
} else {
d->lp = 0;
j++;
}
}
}
void alN_PVoiceNew(N_PVoice *mv, ALDMANew dmaNew, ALHeap *hp)
{
mv->dc_state = alHeapAlloc(hp, 1, sizeof(ADPCM_STATE));
mv->dc_lstate = alHeapAlloc(hp, 1, sizeof(ADPCM_STATE));
mv->dc_dma = dmaNew(&mv->dc_dmaState);
mv->dc_lastsam = 0;
mv->dc_first = 1;
mv->dc_memin = 0;
mv->rs_state = alHeapAlloc(hp, 1, sizeof(RESAMPLE_STATE));
mv->rs_delta = 0.0;
mv->rs_first = 1;
mv->rs_ratio = 1.0;
mv->rs_upitch = 0;
mv->em_state = alHeapAlloc(hp, 1, sizeof(ENVMIX_STATE));
mv->em_first = 1;
mv->em_motion = AL_STOPPED;
mv->em_volume = 1;
mv->em_ltgt = 1;
mv->em_rtgt = 1;
mv->em_cvolL = 1;
mv->em_cvolR = 1;
mv->em_dryamt = 0;
mv->em_wetamt = 0;
mv->em_lratm = 1;
mv->em_lratl = 0;
mv->em_lratm = 1;
mv->em_lratl = 0;
mv->em_delta = 0;
mv->em_segEnd = 0;
mv->em_pan = 0;
mv->em_ctrlList = 0;
mv->em_ctrlTail = 0;
}

View File

@@ -0,0 +1,40 @@
#include <ultra64.h>
#include "n_synth.h"
s32
n_alEnvmixerParam(N_PVoice *filter, s32 paramID, void *param)
{
N_PVoice *e = filter;
switch (paramID) {
case (AL_FILTER_ADD_UPDATE):
if (e->em_ctrlTail) {
e->em_ctrlTail->next = (ALParam *)param;
} else {
e->em_ctrlList = (ALParam *)param;
}
e->em_ctrlTail = (ALParam *)param;
break;
case (AL_FILTER_RESET):
e->em_first = 1;
e->em_motion = AL_STOPPED;
e->em_volume = 1;
e->rs_delta = 0.0;
e->rs_first = 1;
e->rs_upitch = 0;
n_alLoadParam(e, AL_FILTER_RESET, param);
break;
case (AL_FILTER_START):
e->em_motion = AL_PLAYING;
break;
default:
#if 1
n_alLoadParam(e, paramID, param);
#else
n_alResampleParam(e, paramID, param);
#endif
break;
}
return 0;
}

View File

@@ -0,0 +1,87 @@
#include <ultra64.h>
#include "n_synth.h"
#define ADPCMFBYTES 9
int
n_alLoadParam(N_PVoice *v, s32 paramID, void *param)
{
ALLoadFilter *a = (ALLoadFilter *) v;
switch (paramID) {
case (AL_FILTER_SET_WAVETABLE):
v->dc_table = (ALWaveTable *) param;
v->dc_memin = (s32) v->dc_table->base;
v->dc_sample = 0;
switch (v->dc_table->type){
case (AL_ADPCM_WAVE):
/*
* Set up the correct handler
*/
/*
* Make sure the table length is an integer number of
* frames
*/
v->dc_table->len = ADPCMFBYTES *
((s32) (v->dc_table->len/ADPCMFBYTES));
v->dc_bookSize = 2*v->dc_table->waveInfo.adpcmWave.book->order*
v->dc_table->waveInfo.adpcmWave.book->npredictors*ADPCMVSIZE;
if (v->dc_table->waveInfo.adpcmWave.loop) {
v->dc_loop.start = v->dc_table->waveInfo.adpcmWave.loop->start;
v->dc_loop.end = v->dc_table->waveInfo.adpcmWave.loop->end;
v->dc_loop.count = v->dc_table->waveInfo.adpcmWave.loop->count;
alCopy(v->dc_table->waveInfo.adpcmWave.loop->state,
v->dc_lstate, sizeof(ADPCM_STATE));
} else {
v->dc_loop.start = v->dc_loop.end = v->dc_loop.count = 0;
}
break;
case (AL_RAW16_WAVE):
//f->handler = alRaw16Pull;
if (v->dc_table->waveInfo.rawWave.loop) {
v->dc_loop.start = v->dc_table->waveInfo.rawWave.loop->start;
v->dc_loop.end = v->dc_table->waveInfo.rawWave.loop->end;
v->dc_loop.count = v->dc_table->waveInfo.rawWave.loop->count;
} else {
v->dc_loop.start = v->dc_loop.end = v->dc_loop.count = 0;
}
break;
default:
break;
}
break;
case (AL_FILTER_RESET):
v->dc_lastsam = 0;
v->dc_first = 1;
v->dc_sample = 0;
/* sct 2/14/96 - Check table since it is initialized to null and */
/* Get loop info according to table type. */
if (v->dc_table)
{
v->dc_memin = (s32) v->dc_table->base;
if (v->dc_table->type == AL_ADPCM_WAVE)
{
if (v->dc_table->waveInfo.adpcmWave.loop)
v->dc_loop.count = v->dc_table->waveInfo.adpcmWave.loop->count;
}
else if (v->dc_table->type == AL_RAW16_WAVE)
{
if (v->dc_table->waveInfo.rawWave.loop)
v->dc_loop.count = v->dc_table->waveInfo.rawWave.loop->count;
}
}
break;
default:
break;
}
}

View File

@@ -0,0 +1,28 @@
#include <ultra64.h>
#include "n_synth.h"
Acmd *n_alMainBusPull( s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
#ifndef N_MICRO
aClearBuffer(ptr++, AL_MAIN_L_OUT, FIXED_SAMPLE<<1);
aClearBuffer(ptr++, AL_MAIN_R_OUT, FIXED_SAMPLE<<1);
#else
aClearBuffer(ptr++, N_AL_MAIN_L_OUT, N_AL_DIVIDED<<1);
#endif
ptr = (n_syn->mainBus->filter.handler)(sampleOffset,ptr);
#ifndef N_MICRO
aSetBuffer(ptr++, 0, 0, 0, FIXED_SAMPLE<<1);
aMix(ptr++, 0, 0x7fff, AL_AUX_L_OUT, AL_MAIN_L_OUT);
aMix(ptr++, 0, 0x7fff, AL_AUX_R_OUT, AL_MAIN_R_OUT);
#else
aMix(ptr++, 0, 0x7fff, N_AL_AUX_L_OUT, N_AL_MAIN_L_OUT);
aMix(ptr++, 0, 0x7fff, N_AL_AUX_R_OUT, N_AL_MAIN_R_OUT);
#endif
return ptr;
}

View File

@@ -0,0 +1,116 @@
#include <ultra64.h>
#include "n_synth.h"
#ifdef AUD_PROFILE
extern u32 cnt_index, resampler_num, resampler_cnt, resampler_max, resampler_min, lastCnt[];
#endif
/***********************************************************************
* Resampler filter public interfaces
***********************************************************************/
Acmd *n_alResamplePull(N_PVoice *e, s16 *outp, Acmd *p)
{
Acmd *ptr = p;
s16 inp;
s32 inCount;
s32 incr;
f32 finCount;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
#ifndef N_MICRO
inp = AL_DECODER_OUT;
#else
inp = N_AL_DECODER_OUT;
#endif
/*
* check if resampler is required
*/
if (e->rs_upitch) {
ptr = n_alAdpcmPull(e, &inp, FIXED_SAMPLE, p);
aDMEMMove(ptr++, inp, *outp , FIXED_SAMPLE<<1);
} else {
/*
* clip to maximum allowable pitch
* FIXME: should we check for some minimum as well?
*/
if (e->rs_ratio > MAX_RATIO) e->rs_ratio = MAX_RATIO;
/*
* quantize the pitch
*/
e->rs_ratio = (s32)(e->rs_ratio * UNITY_PITCH);
e->rs_ratio = e->rs_ratio / UNITY_PITCH;
/*
* determine how many samples to generate
*/
finCount = e->rs_delta + (e->rs_ratio * (f32)FIXED_SAMPLE);
inCount = (s32) finCount;
e->rs_delta = finCount - (f32)inCount;
/*
* ask all filters upstream from us to build their command
* lists.
*/
ptr = n_alAdpcmPull(e, &inp, inCount, p);
/*
* construct our portion of the command list
*/
incr = (s32)(e->rs_ratio * UNITY_PITCH);
#ifndef N_MICRO
aSetBuffer(ptr++, 0, inp , *outp, FIXED_SAMPLE<<1);
aResample(ptr++, e->rs_first, incr, osVirtualToPhysical(e->rs_state));
#else
#include "n_resample_add01.c_"
#endif
e->rs_first = 0;
}
#ifdef AUD_PROFILE
PROFILE_AUD(resampler_num, resampler_cnt, resampler_max, resampler_min);
#endif
return ptr;
}
s32 n_alResampleParam(N_PVoice *filter, s32 paramID, void *param)
{
N_PVoice *r = filter;
union {
f32 f;
s32 i;
} data;
switch (paramID) {
#if 0
case (AL_FILTER_RESET):
r->rs_delta = 0.0;
r->rs_first = 1;
r->rs_upitch = 0;
n_alLoadParam(filter, AL_FILTER_RESET, 0);
break;
case (AL_FILTER_START):
n_alLoadParam(filter, AL_FILTER_START, 0);
break;
case (AL_FILTER_SET_PITCH):
data.i = (s32) param;
r->rs_ratio = data.f;
break;
case (AL_FILTER_SET_UNITY_PITCH):
r->rs_upitch = 1;
break;
#endif
default:
n_alLoadParam(filter, paramID, param);
break;
}
return 0;
}

View File

@@ -0,0 +1,2 @@
n_aResample(ptr++, osVirtualToPhysical(e->rs_state), e->rs_first, incr, inp, 0);

View File

@@ -0,0 +1,19 @@
#include <ultra64.h>
#include "n_synth.h"
Acmd *n_alSavePull( s32 sampleOffset, Acmd *p)
{
Acmd *ptr = p;
ptr = n_alMainBusPull(sampleOffset, ptr);
#ifndef N_MICRO
aSetBuffer (ptr++, 0, 0, 0, FIXED_SAMPLE<<1);
aInterleave(ptr++, AL_MAIN_L_OUT, AL_MAIN_R_OUT);
aSetBuffer (ptr++, 0, 0, 0, FIXED_SAMPLE<<2);
aSaveBuffer(ptr++, n_syn->sv_dramout);
#else
#include "n_save_add01.c_"
#endif
return ptr;
}

View File

@@ -0,0 +1,2 @@
n_aInterleave(ptr++);
n_aSaveBuffer(ptr++, FIXED_SAMPLE<<2, 0, n_syn->sv_dramout);

View File

@@ -0,0 +1,68 @@
#include <ultra64.h>
#include "synthInternals.h"
#include "n_synth.h"
void n_alSynAddPlayer( ALPlayer *client)
{
OSIntMask mask = osSetIntMask(OS_IM_NONE);
client->samplesLeft = n_syn->curSamples;
client->next = n_syn->head;
n_syn->head = client;
osSetIntMask(mask);
}
void n_alSynAddSndPlayer( ALPlayer *client)
{
OSIntMask mask = osSetIntMask(OS_IM_NONE);
client->samplesLeft = n_syn->curSamples;
#if 1
client->next = n_syn->head;
n_syn->head = client;
#endif
if( !(n_syn->n_sndp) )
n_syn->n_sndp = client;
osSetIntMask(mask);
}
void n_alSynAddSeqPlayer(ALPlayer *client)
{
OSIntMask mask = osSetIntMask(OS_IM_NONE);
client->samplesLeft = n_syn->curSamples;
client->next = n_syn->head;
n_syn->head = client;
if(n_syn->n_seqp1 == 0){
n_syn->n_seqp1 = client;
}
else if(n_syn->n_seqp2 == 0){
n_syn->n_seqp2 = client;
}
else if(n_syn->unk5C == 0){
n_syn->unk5C = client;
}
else if(n_syn->unk60 == 0){
n_syn->unk60 = client;
}
else if(n_syn->unk64 == 0){
n_syn->unk64 = client;
}
else if(n_syn->unk68 == 0){
n_syn->unk68 = client;
}
else if(n_syn->unk6C == 0){
n_syn->unk6C = client;
}
else if(n_syn->unk70 == 0){
n_syn->unk70 = client;
}
osSetIntMask(mask);
}

View File

@@ -0,0 +1,10 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
ALFxRef n_alSynAllocFX( s16 bus, ALSynConfig *c, ALHeap *hp)
{
n_alFxNew(&n_syn->auxBus->fx_array[bus], c, hp);
return(n_syn->auxBus->fx_array[bus]);
}

View File

@@ -0,0 +1,107 @@
#include <ultra64.h>
#include "n_synth.h"
static s32 _n_allocatePVoice(N_PVoice **pvoice, s16 priority);
s32 n_alSynAllocVoice( N_ALVoice *voice, ALVoiceConfig *vc)
{
N_PVoice *pvoice = 0;
ALParam *update;
s32 stolen;
#ifdef _DEBUG
/* need two updates if voice is stolen */
if (drvr->paramList == 0) {
__osError(ERR_ALSYN_NO_UPDATE, 0);
return 0;
} else if (drvr->paramList->next == 0) {
__osError(ERR_ALSYN_NO_UPDATE, 0);
return 0;
}
#endif
voice->priority = vc->priority;
voice->unityPitch = vc->unityPitch;
voice->table = 0;
voice->fxBus = vc->fxBus;
voice->state = AL_STOPPED;
voice->pvoice = 0;
stolen = _n_allocatePVoice(&pvoice, vc->priority);
if (pvoice) { /* if we were able to allocate a voice */
if (stolen) {
pvoice->offset = 512;
pvoice->vvoice->pvoice = 0; /* zero stolen voice */
pvoice->vvoice = voice;
voice->pvoice = pvoice;
/*
* ramp down stolen voice
*/
update = __n_allocParam();
update->delta = n_syn->paramSamples;
update->type = AL_FILTER_SET_VOLUME;
update->data.i = 0;
update->moredata.i = pvoice->offset - 64;
n_alEnvmixerResampleParam(voice->pvoice, AL_FILTER_ADD_UPDATE, update);
/*
* stop stolen voice
*/
update = __n_allocParam();
if (update) {
update->delta = n_syn->paramSamples + pvoice->offset;
update->type = AL_FILTER_STOP_VOICE;
update->next = 0;
n_alEnvmixerResampleParam(voice->pvoice, AL_FILTER_ADD_UPDATE, update);
} else {
#ifdef _DEBUG
__osError(ERR_ALSYN_NO_UPDATE, 0);
#endif
}
} else {
pvoice->offset = 0;
pvoice->vvoice = voice; /* assign new voice */
voice->pvoice = pvoice;
}
}
return (pvoice != 0);
}
static
s32 _n_allocatePVoice(N_PVoice **pvoice, s16 priority)
{
ALLink *dl;
N_PVoice *pv;
s32 stolen = 0;
if ((dl = n_syn->pLameList.next) != 0) { /* check the lame list first */
*pvoice = (N_PVoice *) dl;
alUnlink(dl);
alLink(dl, &n_syn->pAllocList);
} else if ((dl = n_syn->pFreeList.next) != 0) { /* from the free list */
*pvoice = (N_PVoice *) dl;
alUnlink(dl);
alLink(dl, &n_syn->pAllocList);
} else { /* steal one */
for (dl = n_syn->pAllocList.next; dl != 0; dl = dl->next) {
pv = (N_PVoice *)dl;
/*
* if it is lower priority and not already stolen, keep it
* as a candidate for stealing
*/
if ((pv->vvoice->priority <= priority) && (pv->offset == 0)) {
*pvoice = pv;
priority = pv->vvoice->priority;
stolen = 1;
}
}
}
return stolen;
}

View File

@@ -0,0 +1,30 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynFreeVoice(N_ALVoice *voice)
{
ALFilter *f;
ALFreeParam *update;
if (voice->pvoice) {
if (voice->pvoice->offset) { /* if voice was stolen */
update = (ALFreeParam *)__n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* set voice data
*/
update->delta = n_syn->paramSamples + voice->pvoice->offset;
update->type = AL_FILTER_FREE_VOICE;
update->pvoice = (PVoice *)voice->pvoice;
n_alEnvmixerResampleParam(voice->pvoice, AL_FILTER_ADD_UPDATE, update);
} else {
_n_freePVoice(voice->pvoice);
}
voice->pvoice = 0;
}
}

View File

@@ -0,0 +1,29 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynSetFXMix(N_ALVoice *v, u8 fxmix)
{
ALParam *update;
if (v->pvoice) {
/*
* get new update struct from the free list
*/
update = __n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* set offset and fxmix data
*/
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->type = AL_FILTER_SET_FXAMT;
if (fxmix < 0)
update->data.i = -fxmix;
else
update->data.i = fxmix;
update->next = 0;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,27 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynSetPan(N_ALVoice *v, u8 pan)
{
ALParam *update;
ALFilter *f;
if (v->pvoice) {
/*
* get new update struct from the free list
*/
update = __n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* set offset and pan data
*/
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->type = AL_FILTER_SET_PAN;
update->data.i = pan;
update->next = 0;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,27 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynSetPitch( N_ALVoice *v, f32 pitch)
{
ALParam *update;
ALFilter *f;
if (v->pvoice) {
/*
* get new update struct from the free list
*/
update = __n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* set offset and pitch data
*/
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->type = AL_FILTER_SET_PITCH;
update->data.f = pitch;
update->next = 0;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,30 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynSetVol( N_ALVoice *v, s16 volume, ALMicroTime t)
{
ALParam *update;
ALFilter *f;
if (v->pvoice) {
/*
* get new update struct from the free list
*/
update = __n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* set offset and volume data
*/
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->type = AL_FILTER_SET_VOLUME;
update->data.i = volume;
update->moredata.i = _n_timeToSamples( t);
update->next = 0;
//f = v->pvoice->channelKnob;
//(*f->setParam)(f, AL_FILTER_ADD_UPDATE, update);
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,49 @@
/*====================================================================
*
* Copyright 1993, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
* Inc.; the contents of this file may not be disclosed to third
* parties, copied or duplicated in any form, in whole or in part,
* without the prior written permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS
* 252.227-7013, and/or in similar or successor clauses in the FAR,
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
* Copyright Laws of the United States.
*====================================================================*/
#include <os_internal.h>
#include <ultraerror.h>
#include "n_synth.h"
void n_alSynStartVoice( N_ALVoice *v, ALWaveTable *table)
{
ALStartParam *update;
if (v->pvoice) {
update = (ALStartParam *)__n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
/*
* send the start message to the motion control filter
*/
#ifdef SAMPLE_ROUND
update->delta = SAMPLE184( n_syn->paramSamples + v->pvoice->offset);
#else
update->delta = n_syn->paramSamples + v->pvoice->offset;
#endif
update->type = AL_FILTER_START_VOICE;
update->wave = table;
update->next = 0;
update->unity = v->unityPitch;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,42 @@
#include <ultra64.h>
#include "synthInternals.h"
#include "n_synth.h"
void n_alSynStartVoiceParams(N_ALVoice *v, ALWaveTable *w,
f32 pitch, s16 vol, ALPan pan, u8 fxmix,
ALMicroTime t)
{
ALStartParamAlt *update;
if ( v->pvoice) {
/*
* get new update struct from the free list
*/
update = (ALStartParamAlt *)__n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
if (fxmix < 0)
fxmix = -fxmix;
/*
* set offset and fxmix data
*/
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->next = 0;
update->type = AL_FILTER_START_VOICE_ALT;
update->unity = v->unityPitch;
update->pan = pan;
update->volume = vol;
update->fxMix = fxmix;
update->pitch = pitch;
update->samples = _n_timeToSamples( t);
update->wave = w;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,20 @@
#include <ultra64.h>
#include "n_synth.h"
void n_alSynStopVoice( N_ALVoice *v)
{
ALParam *update;
if (v->pvoice) {
update = __n_allocParam();
ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE);
update->delta = n_syn->paramSamples + v->pvoice->offset;
update->type = AL_FILTER_STOP_VOICE;
update->next = 0;
n_alEnvmixerResampleParam(v->pvoice, AL_FILTER_ADD_UPDATE, update);
}
}

View File

@@ -0,0 +1,359 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_synth.h"
#ifndef assert
#define assert(s)
#endif
extern ALCmdHandler n_alAuxBusPull;
extern ALCmdHandler func_8025FE6C;
extern void alN_PVoiceNew(N_PVoice *mv, ALDMANew dmaNew, ALHeap *hp);
#ifdef AUD_PROFILE
#include <os.h>
extern u32 cnt_index, drvr_num, drvr_cnt, drvr_max, drvr_min, lastCnt[];
extern u32 client_num, client_cnt, client_max, client_min;
#endif
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
static s32 func_8025C370(ALPlayer **client);
static s32 _n_timeToSamplesNoRound(s32 micros);
/***********************************************************************
* Synthesis driver public interfaces
***********************************************************************/
void n_alSynNew(ALSynConfig *c)
{
s32 i;
N_PVoice *pv;
N_PVoice *pvoices;
ALHeap *hp = c->heap;
ALFilter *sources;
ALParam *params;
ALParam *paramPtr;
n_syn->head = NULL;
n_syn->n_seqp1 = NULL;
n_syn->n_seqp2 = NULL;
n_syn->unk5C = NULL;
n_syn->unk60 = NULL;
n_syn->unk64 = NULL;
n_syn->unk68 = NULL;
n_syn->unk6C = NULL;
n_syn->unk70 = NULL;
n_syn->n_sndp = NULL;
n_syn->numPVoices = c->maxPVoices;
n_syn->curSamples = 0;
n_syn->paramSamples = 0;
n_syn->outputRate = c->outputRate;
n_syn->maxOutSamples = N_AL_MAX_RSP_SAMPLES;
n_syn->dma = (ALDMANew) c->dmaproc;
n_syn->sv_dramout = 0;
n_syn->sv_first = 1;
/*
* allocate and initialize the auxilliary effects bus. at present
* we only support 1 effects bus.
*/
n_syn->auxBus = alHeapAlloc(hp, 1, sizeof(N_ALAuxBus));
n_syn->auxBus->sourceCount = 0;
n_syn->auxBus->maxSources = c->maxPVoices;
n_syn->auxBus->sources = alHeapAlloc(hp, c->maxPVoices, sizeof(ALFilter *));
/*
* allocate and initialize the main bus.
*/
n_syn->mainBus = alHeapAlloc(hp, 1, sizeof(N_ALMainBus));
if (c->fxType != AL_FX_NONE){
/*
* Allocate an effect and set parameters
*/
n_syn->auxBus->fx = n_alSynAllocFX(0, c, hp);
n_syn->mainBus->filter.handler = &func_8025FE6C;
} else{
/*
* Connect the aux bus to the main bus
*/
n_syn->mainBus->filter.handler = &n_alAuxBusPull;
}
/*
* Build the physical voice lists
*/
n_syn->pFreeList.next = 0;
n_syn->pFreeList.prev = 0;
n_syn->pLameList.next = 0;
n_syn->pLameList.prev = 0;
n_syn->pAllocList.next = 0;
n_syn->pAllocList.prev = 0;
pvoices = alHeapAlloc(hp, c->maxPVoices, sizeof(N_PVoice));
for (i = 0; i < c->maxPVoices; i++) {
pv = &pvoices[i];
alLink((ALLink *)pv, &n_syn->pFreeList);
pv->vvoice = 0;
alN_PVoiceNew(pv, n_syn->dma, hp);
n_syn->auxBus->sources[n_syn->auxBus->sourceCount] = pv;
n_syn->auxBus->sourceCount++;
}
/*
* build the parameter update list
*/
params = alHeapAlloc(hp, c->maxUpdates, sizeof(ALParam));
n_syn->paramList = 0;
for (i = 0; i < c->maxUpdates; i++) {
paramPtr= &params[i];
paramPtr->next = n_syn->paramList;
n_syn->paramList = paramPtr;
}
n_syn->heap = hp;
}
/*
* slAudioFrame() is called every video frame, and is based on the video
* frame interrupt. It is assumed to be an accurate time source for the
* clients.
*/
Acmd *n_alAudioFrame(Acmd *cmdList, s32 *cmdLen, s16 *outBuf, s32 outLen)
{
ALPlayer *client;
ALFilter *output;
s16 tmp; /* Starting buffer in DMEM */
Acmd *cmdlEnd = cmdList;
s32 nOut;
s16 *lOutBuf = outBuf;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
if (n_syn->head == 0) {
*cmdLen = 0;
return cmdList; /* nothing to do */
}
/*
* run down list of clients and execute callback if needed this
* subframe. Here we do all the work for the frame at the
* start. Time offsets that occur before the next frame are
* executed "early".
*/
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
/*
* paramSamples = time of next parameter change.
* curSamples = current sample time.
* so paramSamples - curSamples is the time until the next parameter change.
* if the next parameter change occurs within this frame time (outLen),
* then call back the client that contains the parameter change.
* Note, paramSamples must be rounded down to 16 sample boundary for use
* during the client handler.
*/
for (n_syn->paramSamples = func_8025C370(&client);
n_syn->paramSamples - n_syn->curSamples < outLen;
n_syn->paramSamples = func_8025C370(&client))
{
n_syn->paramSamples &= ~0xf;
client->samplesLeft += _n_timeToSamplesNoRound((*client->handler)(client));
}
/* for safety's sake, always store paramSamples aligned to 16 sample boundary.
* this way, if an voice handler routine gets called outside the ALVoiceHandler
* routine (alSynAllocVoice) it will get timestamped with an aligned value and
* will be processed immediately next audio frame.
*/
n_syn->paramSamples &= ~0xf;
#ifdef AUD_PROFILE
PROFILE_AUD(client_num, client_cnt, client_max, client_min);
#endif
/*
* Now build the command list in small chunks
*/
while (outLen > 0){
nOut = MIN(n_syn->maxOutSamples, outLen);
/*
* construct the command list for each physical voice by calling
* the head of the filter chain.
*/
n_syn->sv_dramout = (s32) lOutBuf;
cmdlEnd = n_alSavePull(n_syn->curSamples, cmdlEnd);
outLen -= nOut;
lOutBuf += nOut<<1; /* For Stereo */
n_syn->curSamples += nOut;
}
*cmdLen = (s32) (cmdlEnd - cmdList);
_n_collectPVoices(); /* collect free physical voices */
#ifdef AUD_PROFILE
PROFILE_AUD(drvr_num, drvr_cnt, drvr_max, drvr_min);
#endif
return cmdlEnd;
}
/***********************************************************************
* Synthesis driver private interfaces
***********************************************************************/
ALParam *__allocParam()
{
ALParam *update = 0;
if (n_syn->paramList) {
update = n_syn->paramList;
n_syn->paramList =n_syn->paramList->next;
update->next = 0;
}
return update;
}
void __n_freeParam(ALParam *param)
{
param->next = n_syn->paramList;
n_syn->paramList = param;
}
void _n_collectPVoices()
{
ALLink *dl;
N_PVoice *pv;
while ((dl = n_syn->pLameList.next) != 0) {
pv = (N_PVoice *)dl;
/* ### remove from mixer */
alUnlink(dl);
alLink(dl, &n_syn->pFreeList);
}
}
void _n_freePVoice(N_PVoice *pvoice)
{
/*
* move the voice from the allocated list to the lame list
*/
alUnlink((ALLink *)pvoice);
alLink((ALLink *)pvoice, &n_syn->pLameList);
}
/*
Add 0.5 to adjust the average affect of
the truncation error produced by casting
a float to an int.
*/
s32 _n_timeToSamplesNoRound(s32 micros)
{
f32 tmp = ((f32)micros) * n_syn->outputRate / 1000000.0 + 0.5;
return (s32)tmp;
}
s32 _n_timeToSamples(s32 micros)
{
return _n_timeToSamplesNoRound(micros) & ~0xf;
}
static s32 func_8025C370(ALPlayer **client)
{
ALMicroTime idelta;
ALMicroTime delta = 0x7fffffff; /* max delta for s32 */
ALPlayer *cl;
*client = 0;
if(n_syn->n_sndp != NULL){
idelta = (n_syn->n_sndp->samplesLeft - n_syn->curSamples);
if (idelta < delta) {
*client = n_syn->n_sndp;
delta = idelta;
}
}
cl = n_syn->n_seqp1;
if(cl != NULL){
idelta = (cl->samplesLeft - n_syn->curSamples);
if (idelta < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->n_seqp2;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk5C;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk60;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk64;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk68;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk6C;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
cl = n_syn->unk70;
if(cl != NULL){
if ((cl->samplesLeft - n_syn->curSamples) < delta) {
*client = cl;
delta = idelta;
}
}
return (*client)->samplesLeft;
}

View File

@@ -0,0 +1,125 @@
#include <ultra64.h>
#include "synthInternals.h"
#ifdef AUD_PROFILE
extern u32 cnt_index, resampler_num, resampler_cnt, resampler_max, resampler_min, lastCnt[];
#endif
/***********************************************************************
* Resampler filter public interfaces
***********************************************************************/
Acmd *alResamplePull(void *filter, s16 *outp, s32 outCnt, s32 sampleOffset, Acmd *p)
{
ALResampler *f = (ALResampler *)filter;
Acmd *ptr = p;
s16 inp;
s32 inCount;
ALFilter *source = f->filter.source;
s32 incr;
f32 finCount;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
inp = AL_DECODER_OUT;
if (!outCnt)
return ptr;
/*
* check if resampler is required
*/
if (f->upitch) {
ptr = (*source->handler)(source, &inp, outCnt, sampleOffset, p);
aDMEMMove(ptr++, inp, *outp, outCnt<<1);
} else {
/*
* clip to maximum allowable pitch
* FIXME: should we check for some minimum as well?
*/
if (f->ratio > MAX_RATIO) f->ratio = MAX_RATIO;
/*
* quantize the pitch
*/
f->ratio = (s32)(f->ratio * UNITY_PITCH);
f->ratio = f->ratio / UNITY_PITCH;
/*
* determine how many samples to generate
*/
finCount = f->delta + (f->ratio * (f32) outCnt);
inCount = (s32) finCount;
f->delta = finCount - (f32)inCount;
/*
* ask all filters upstream from us to build their command
* lists.
*/
ptr = (*source->handler)(source, &inp, inCount, sampleOffset, p);
/*
* construct our portion of the command list
*/
incr = (s32)(f->ratio * UNITY_PITCH);
aSetBuffer(ptr++, 0, inp, *outp, outCnt<<1);
aResample(ptr++, f->first, incr, osVirtualToPhysical(f->state));
f->first = 0;
}
#ifdef AUD_PROFILE
PROFILE_AUD(resampler_num, resampler_cnt, resampler_max, resampler_min);
#endif
return ptr;
}
s32 alResampleParam(void *filter, s32 paramID, void *param)
{
ALFilter *f = (ALFilter *) filter;
ALResampler *r = (ALResampler *) filter;
union {
f32 f;
s32 i;
} data;
switch (paramID) {
case (AL_FILTER_SET_SOURCE):
f->source = (ALFilter *) param;
break;
case (AL_FILTER_RESET):
r->delta = 0.0;
r->first = 1;
r->motion = AL_STOPPED;
r->upitch = 0;
if (f->source)
(*f->source->setParam)(f->source, AL_FILTER_RESET, 0);
break;
case (AL_FILTER_START):
r->motion = AL_PLAYING;
if (f->source)
(*f->source->setParam)(f->source, AL_FILTER_START, 0);
break;
case (AL_FILTER_SET_PITCH):
data.i = (s32) param;
r->ratio = data.f;
break;
case (AL_FILTER_SET_UNITY_PITCH):
r->upitch = 1;
break;
default:
if (f->source)
(*f->source->setParam)(f->source, paramID, param);
break;
}
return 0;
}

View File

@@ -0,0 +1,431 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "synthInternals.h"
#include "initfx.h"
#ifndef assert
#define assert(s)
#endif
#define RANGE 2.0
extern ALGlobals *alGlobals;
#ifdef AUD_PROFILE
extern u32 cnt_index, reverb_num, reverb_cnt, reverb_max, reverb_min, lastCnt[];
extern u32 load_num, load_cnt, load_max, load_min, save_num, save_cnt, save_max, save_min;
#endif
/*
* macros
*/
#define SWAP(in, out) \
{ \
s16 t = out; \
out = in; \
in = t; \
}
Acmd *_loadOutputBuffer(ALFx *r, ALDelay *d, s32 buff, s32 incount, Acmd *p);
Acmd *_loadBuffer(ALFx *r, s16 *curr_ptr, s32 buff, s32 count, Acmd *p);
Acmd *_saveBuffer(ALFx *r, s16 *curr_ptr, s32 buff, s32 count, Acmd *p);
Acmd *_filterBuffer(ALLowPass *lp, s32 buff, s32 count, Acmd *p);
f32 _doModFunc(ALDelay *d, s32 count);
static s32 L_INC[] = { L0_INC, L1_INC, L2_INC };
/***********************************************************************
* Reverb filter public interfaces
***********************************************************************/
Acmd *alFxPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset,
Acmd *p)
{
Acmd *ptr = p;
ALFx *r = (ALFx *)filter;
ALFilter *source = r->filter.source;
s16 i, buff1, buff2, input, output;
s16 *in_ptr, *out_ptr, gain, *prev_out_ptr = 0;
ALDelay *d, *pd;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
assert(source);
/*
* pull channels going into this effect first
*/
ptr = (*source->handler)(source, outp, outCount, sampleOffset, p);
input = AL_AUX_L_OUT;
output = AL_AUX_R_OUT;
buff1 = AL_TEMP_0;
buff2 = AL_TEMP_1;
aSetBuffer(ptr++, 0, 0, 0, outCount<<1); /* set the buffer size */
aMix(ptr++, 0, 0xda83, AL_AUX_L_OUT, input); /* .707L = L - .293L */
aMix(ptr++, 0, 0x5a82, AL_AUX_R_OUT, input); /* mix the AuxL and AuxR into the AuxL */
/* and write the mixed value to the delay line at r->input */
ptr = _saveBuffer(r, r->input, input, outCount, ptr);
aClearBuffer(ptr++, output, outCount<<1); /* clear the AL_AUX_R_OUT */
for (i = 0; i < r->section_count; i++) {
d = &r->delay[i]; /* get the ALDelay structure */
in_ptr = &r->input[-d->input];
out_ptr = &r->input[-d->output];
if (in_ptr == prev_out_ptr) {
SWAP(buff1, buff2);
} else { /* load data at in_ptr into buff1 */
ptr = _loadBuffer(r, in_ptr, buff1, outCount, ptr);
}
ptr = _loadOutputBuffer(r, d, buff2, outCount, ptr);
if (d->ffcoef) {
aMix(ptr++, 0, (u16)d->ffcoef, buff1, buff2);
if (!d->rs && !d->lp) {
ptr = _saveBuffer(r, out_ptr, buff2, outCount, ptr);
}
}
if (d->fbcoef) {
aMix(ptr++, 0, (u16)d->fbcoef, buff2, buff1);
ptr = _saveBuffer(r, in_ptr, buff1, outCount, ptr);
}
if (d->lp)
ptr = _filterBuffer(d->lp, buff2, outCount, ptr);
if (!d->rs)
ptr = _saveBuffer(r, out_ptr, buff2, outCount, ptr);
if (d->gain)
aMix(ptr++, 0, (u16)d->gain, buff2, output);
prev_out_ptr = &r->input[d->output];
}
/*
* bump the master delay line input pointer
* modulo the length
*/
r->input += outCount;
if (r->input > &r->base[r->length])
r->input -= r->length;
/*
* output already in AL_AUX_R_OUT
* just copy to AL_AUX_L_OUT
*/
aDMEMMove(ptr++, output, AL_AUX_L_OUT, outCount<<1);
#ifdef AUD_PROFILE
PROFILE_AUD(reverb_num, reverb_cnt, reverb_max, reverb_min);
#endif
return ptr;
}
s32 alFxParam(void *filter, s32 paramID, void *param)
{
if(paramID == AL_FILTER_SET_SOURCE)
{
ALFilter *f = (ALFilter *) filter;
f->source = (ALFilter*) param;
}
return 0;
}
/*
* This routine gets called by alSynSetFXParam. No checking takes place to
* verify the validity of the paramID or the param value. input and output
* values must be 8 byte aligned, so round down any param passed.
*/
s32 alFxParamHdl(void *filter, s32 paramID, void *param)
{
ALFx *f = (ALFx *) filter;
s32 p = (paramID - 2) % 8;
s32 s = (paramID - 2) / 8;
s32 val = *(s32*)param;
#define INPUT_PARAM 0
#define OUTPUT_PARAM 1
#define FBCOEF_PARAM 2
#define FFCOEF_PARAM 3
#define GAIN_PARAM 4
#define CHORUSRATE_PARAM 5
#define CHORUSDEPTH_PARAM 6
#define LPFILT_PARAM 7
switch(p)
{
case INPUT_PARAM:
f->delay[s].input = (u32)val & 0xFFFFFFF8;
break;
case OUTPUT_PARAM:
f->delay[s].output = (u32)val & 0xFFFFFFF8;
break;
case FFCOEF_PARAM:
f->delay[s].ffcoef = (s16)val;
break;
case FBCOEF_PARAM:
f->delay[s].fbcoef = (s16)val;
break;
case GAIN_PARAM:
f->delay[s].gain = (s16)val;
break;
case CHORUSRATE_PARAM:
/* f->delay[s].rsinc = ((f32)val)/0xffffff; */
f->delay[s].rsinc = ((((f32)val)/1000) * RANGE)/alGlobals->drvr.outputRate;
break;
/*
* the following constant is derived from:
*
* ratio = 2^(cents/1200)
*
* and therefore for hundredths of a cent
* x
* ln(ratio) = ---------------
* (120,000)/ln(2)
* where
* 120,000/ln(2) = 173123.40...
*/
#define CONVERT 173123.404906676
#define LENGTH (f->delay[s].output - f->delay[s].input)
case CHORUSDEPTH_PARAM:
/*f->delay[s].rsgain = (((f32)val) / CONVERT) * LENGTH; */
f->delay[s].rsgain = (((f32)val) / CONVERT) * LENGTH;
break;
case LPFILT_PARAM:
if(f->delay[s].lp)
{
f->delay[s].lp->fc = (s16)val;
init_lpfilter(f->delay[s].lp);
}
break;
}
return 0;
}
Acmd *_loadOutputBuffer(ALFx *r, ALDelay *d, s32 buff, s32 incount, Acmd *p)
{
Acmd *ptr = p;
s32 ratio, count, rbuff = AL_TEMP_2;
s16 *out_ptr;
f32 fincount, fratio, delta;
s32 ramalign = 0, length;
static f32 val=0.0, lastval=-10.0;
static f32 blob=0;
/*
* The following section implements the chorus resampling. Modulate where you pull
* the samples from, since you need varying amounts of samples.
*/
if (d->rs) {
length = d->output - d->input;
delta = _doModFunc(d, incount); /* get the number of samples to modulate by */
/*
* find ratio of delta to delay length and quantize
* to same resolution as resampler
*/
delta /= length; /* convert delta from number of samples to a pitch ratio */
delta = (s32)(delta * UNITY_PITCH); /* quantize to value microcode will use */
delta = delta / UNITY_PITCH;
fratio = 1.0 - delta; /* pitch ratio needs to be centered around 1, not zero */
/* d->rs->delta is the difference between the fractional and integer value
* of the samples needed. fratio * incount + rs->delta gives the number of samples
* needed for this frame.
*/
fincount = d->rs->delta + (fratio * (f32)incount);
count = (s32) fincount; /* quantize to s32 */
d->rs->delta = fincount - (f32)count; /* calculate the round off and store */
/*
* d->rsdelta is amount the out_ptr has deviated from its starting position.
* You calc the out_ptr by taking d->output - d->rsdelta, and then using the
* negative of that as an index into the delay buffer. loadBuffer that uses this
* value then bumps it up if it is below the delay buffer.
*/
out_ptr = &r->input[-(d->output - d->rsdelta)];
ramalign = ((s32)out_ptr & 0x7) >> 1; /* calculate the number of samples needed
to align the buffer*/
#ifdef _DEBUG
#if 0
if(length > 0) {
if (length - d->rsdelta > (s32)r->length) {
__osError(ERR_ALMODDELAYOVERFLOW, 1, length - d->rsdelta - r->length);
}
}
else if(length < 0) {
if ((-length) - d->rsdelta > (s32)r->length) {
__osError(ERR_ALMODDELAYOVERFLOW, 1, (-length) - d->rsdelta - r->length);
}
}
#endif
#endif
/* load the rbuff with samples, note that there will be ramalign worth of
* samples at the begining which you don't care about. */
ptr = _loadBuffer(r, out_ptr - ramalign, rbuff, count + ramalign, ptr);
/* convert fratio to 16 bit fraction for microcode use */
ratio = (s32)(fratio * UNITY_PITCH);
/* set the buffers, and do the resample */
aSetBuffer(ptr++, 0, rbuff + (ramalign<<1), buff, incount<<1);
aResample(ptr++, d->rs->first, ratio, osVirtualToPhysical(d->rs->state));
d->rs->first = 0; /* turn off first time flag */
d->rsdelta += count - incount; /* add the number of samples to d->rsdelta */
} else {
out_ptr = &r->input[-d->output];
ptr = _loadBuffer(r, out_ptr, buff, incount, ptr);
}
return ptr;
}
/*
* This routine is for loading data from the delay line buff. If the
* address of curr_ptr < r->base, it will force it to be within r->base
* space, If the load goes past the end of r->base it will wrap around.
* Cause count bytes of data at curr_ptr (within the delay line) to be
* loaded into buff. (Buff is a dmem buffer)
*/
Acmd *_loadBuffer(ALFx *r, s16 *curr_ptr, s32 buff, s32 count, Acmd *p)
{
Acmd *ptr = p;
s32 after_end, before_end;
s16 *updated_ptr, *delay_end;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
delay_end = &r->base[r->length];
#ifdef _DEBUG
if(curr_ptr > delay_end)
__osError(ERR_ALMODDELAYOVERFLOW, 1, delay_end - curr_ptr);
#endif
if (curr_ptr < r->base)
curr_ptr += r->length;
updated_ptr = curr_ptr + count;
if (updated_ptr > delay_end) {
after_end = updated_ptr - delay_end;
before_end = delay_end - curr_ptr;
aSetBuffer(ptr++, 0, buff, 0, before_end<<1);
aLoadBuffer(ptr++, osVirtualToPhysical(curr_ptr));
aSetBuffer(ptr++, 0, buff+(before_end<<1), 0, after_end<<1);
aLoadBuffer(ptr++, osVirtualToPhysical(r->base));
} else {
aSetBuffer(ptr++, 0, buff, 0, count<<1);
aLoadBuffer(ptr++, osVirtualToPhysical(curr_ptr));
}
aSetBuffer(ptr++, 0, 0, 0, count<<1);
#ifdef AUD_PROFILE
PROFILE_AUD(load_num, load_cnt, load_max, load_min);
#endif
return ptr;
}
/*
* This routine is for writing data to the delay line buff. If the
* address of curr_ptr < r->base, it will force it to be within r->base
* space. If the write goes past the end of r->base, it will wrap around
* Cause count bytes of data at buff to be written to delay line, curr_ptr.
*/
Acmd *_saveBuffer(ALFx *r, s16 *curr_ptr, s32 buff, s32 count, Acmd *p)
{
Acmd *ptr = p;
s32 after_end, before_end;
s16 *updated_ptr, *delay_end;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
delay_end = &r->base[r->length];
if (curr_ptr < r->base) /* probably just security */
curr_ptr += r->length; /* shouldn't occur */
updated_ptr = curr_ptr + count;
if (updated_ptr > delay_end) { /* if the data wraps past end of r->base */
after_end = updated_ptr - delay_end;
before_end = delay_end - curr_ptr;
aSetBuffer(ptr++, 0, 0, buff, before_end<<1);
aSaveBuffer(ptr++, osVirtualToPhysical(curr_ptr));
aSetBuffer(ptr++, 0, 0, buff+(before_end<<1), after_end<<1);
aSaveBuffer(ptr++, osVirtualToPhysical(r->base));
aSetBuffer(ptr++, 0, 0, 0, count<<1);
} else {
aSetBuffer(ptr++, 0, 0, buff, count<<1);
aSaveBuffer(ptr++, osVirtualToPhysical(curr_ptr));
}
#ifdef AUD_PROFILE
PROFILE_AUD(save_num, save_cnt, save_max, save_min);
#endif
return ptr;
}
Acmd *_filterBuffer(ALLowPass *lp, s32 buff, s32 count, Acmd *p)
{
Acmd *ptr = p;
aSetBuffer(ptr++, 0, buff, buff, count<<1);
aLoadADPCM(ptr++, 32, osVirtualToPhysical(lp->fcvec.fccoef));
aPoleFilter(ptr++, lp->first, lp->fgain, osVirtualToPhysical(lp->fstate));
lp->first = 0;
return ptr;
}
/*
* Generate a triangle wave from -1 to 1, and find the current position
* in the wave. (Rate of the wave is controlled by d->rsinc, which is chorus
* rate) Multiply the current triangle wave value by d->rsgain, (chorus depth)
* which is expressed in number of samples back from output pointer the chorus
* should go at it's full chorus. In otherwords, this function returns a number
* of samples the output pointer should modulate backwards.
*/
f32 _doModFunc(ALDelay *d, s32 count)
{
f32 val;
/*
* generate bipolar sawtooth
* from -RANGE to +RANGE
*/
d->rsval += d->rsinc * count;
d->rsval = (d->rsval > RANGE) ? d->rsval-(RANGE*2) : d->rsval;
/*
* convert to monopolar triangle
* from 0 to RANGE
*/
val = d->rsval;
val = (val < 0) ? -val : val;
/*
* convert to bipolar triangle
* from -1 to 1
*/
val -= RANGE/2;
return(d->rsgain * val);
}

View File

@@ -0,0 +1,41 @@
#include <ultra64.h>
#include "synthInternals.h"
Acmd *alSavePull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset,
Acmd *p)
{
Acmd *ptr = p;
ALSave *f = (ALSave *)filter;
ALFilter *source = f->filter.source;
ptr = (*source->handler)(source, outp, outCount, sampleOffset, ptr);
aSetBuffer (ptr++, 0, 0, 0, outCount<<1);
aInterleave(ptr++, AL_MAIN_L_OUT, AL_MAIN_R_OUT);
aSetBuffer (ptr++, 0, 0, 0, outCount<<2);
aSaveBuffer(ptr++, f->dramout);
return ptr;
}
s32 alSaveParam(void *filter, s32 paramID, void *param)
{
ALSave *a = (ALSave *) filter;
ALFilter *f = (ALFilter *) filter;
s32 pp = (s32) param;
switch (paramID) {
case (AL_FILTER_SET_SOURCE):
f->source = (ALFilter *) param;
break;
case (AL_FILTER_SET_DRAM):
a->dramout = pp;
break;
default:
break;
}
return 0;
}

309
src/core1/done/audio/seq.c Normal file
View File

@@ -0,0 +1,309 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
extern f64 D_80278D50;
extern f64 D_80278D58;
#define IFF_FILE_HDR 0x4d546864 /* 'MThd' */
#define IFF_TRACK_HDR 0x4d54726b /* 'MTrk' */
static s32 readVarLen(ALSeq *s);
static u8 read8(ALSeq *s);
static s16 read16(ALSeq *s);
static s32 read32(ALSeq *s);
void alSeqNew(ALSeq *seq, u8 *ptr, s32 len)
{
/*
* load the seqence pointed to by ptr
*/
seq->base = ptr;
seq->len = len;
seq->lastStatus = 0;
seq->lastTicks = 0;
seq->curPtr = ptr;
if (read32(seq) != IFF_FILE_HDR) {
#ifdef _DEBUG
__osError(ERR_ALSEQNOTMIDI, 1, ptr);
#endif
return;
}
read32(seq); /* skip the length field */
if (read16(seq) != 0) {
#ifdef _DEBUG
__osError(ERR_ALSEQNOTMIDI0, 1, ptr);
#endif
return;
}
if (read16(seq) != 1) {
#ifdef _DEBUG
__osError(ERR_ALSEQNUMTRACKS, 1, ptr);
#endif
return;
}
seq->division = read16(seq);
if (seq->division & 0x8000) {
#ifdef _DEBUG
__osError(ERR_ALSEQTIME, 1, ptr);
#endif
return;
}
seq->qnpt = 1.0/(f32)seq->division;
if (read32(seq) != IFF_TRACK_HDR) {
#ifdef _DEBUG
__osError(ERR_ALSEQTRACKHDR, 1, ptr);
#endif
return;
}
read32(seq); /* skip the length field */
seq->trackStart = seq->curPtr;
}
void alSeqNextEvent(ALSeq *seq, ALEvent *event)
{
u8 status;
s16 delta;
s32 len;
s32 deltaTicks;
s32 i;
#ifdef _DEBUG
/* sct 1/17/96 - Warn if curPtr is beyond the end of sequence. */
if (seq->curPtr >= seq->base + seq->len)
__osError(ERR_ALSEQOVERRUN, 0);
#endif
deltaTicks = readVarLen(seq); /* read the delta time */
seq->lastTicks += deltaTicks;
status = read8(seq);
#if _DEBUG
/*
* System exclusives are not supported, so just skip them and read
* the next event
*/
if ((status == 0xf0) || (status == 0xf7)) {
__osError(ERR_ALSEQSYSEX, 0);
len = readVarLen(seq);
for (i = 0; i < len; i++) {
read8(seq);
}
alSeqNextEvent(seq,event);
return;
}
#endif
if (status == AL_MIDI_Meta) {
u8 type = read8(seq);
if (type == AL_MIDI_META_TEMPO) {
event->type = AL_TEMPO_EVT;
event->msg.tempo.ticks = deltaTicks;
event->msg.tempo.status = status;
event->msg.tempo.type = type;
event->msg.tempo.len = read8(seq);
event->msg.tempo.byte1 = read8(seq);
event->msg.tempo.byte2 = read8(seq);
event->msg.tempo.byte3 = read8(seq);
} else if (type == AL_MIDI_META_EOT) {
event->type = AL_SEQ_END_EVT;
event->msg.end.ticks = deltaTicks;
event->msg.end.status = status;
event->msg.end.type = type;
event->msg.end.len = read8(seq);
} else {
#ifdef _DEBUG
__osError(ERR_ALSEQMETA, 1, type);
len = readVarLen(seq);
for (i = 0; i < len; i++) {
read8(seq);
}
alSeqNextEvent(seq,event);
return;
#endif
}
seq->lastStatus = 0;
} else {
event->type = AL_SEQ_MIDI_EVT;
event->msg.midi.ticks = deltaTicks;
if (status & 0x80) {
event->msg.midi.status = status;
event->msg.midi.byte1 = read8(seq);
seq->lastStatus = status;
} else {
/* running status */
event->msg.midi.status = seq->lastStatus;
event->msg.midi.byte1 = status;
}
if (((event->msg.midi.status & 0xf0) != AL_MIDI_ProgramChange) &&
((event->msg.midi.status & 0xf0) != AL_MIDI_ChannelPressure)) {
event->msg.midi.byte2 = read8(seq);
} else {
event->msg.midi.byte2 = 0;
}
}
}
/*
Returns the delta time in ticks for the next event in the sequence.
Assumes that the sequence data pointer is pointing to the delta time.
If the curPtr is at or beyond the end of the sequence, then return FALSE
to indicate no next event.
sct 11/6/95
*/
char __alSeqNextDelta (ALSeq *seq, s32 *pDeltaTicks)
{
u8 * savedPtr;
/* sct 1/16/96 - Put in safety check here to make sure we don't read past sequence data. */
if (seq->curPtr >= seq->base + seq->len)
return FALSE;
savedPtr = seq->curPtr;
*pDeltaTicks = readVarLen(seq); /* read the delta time */
seq->curPtr = savedPtr;
return TRUE;
}
f32 alSeqTicksToSec(ALSeq *seq, s32 ticks, u32 tempo)
{
return ((f32) (((f32)(ticks) * (f32)(tempo)) /
((f32)(seq->division) * 1000000.0)));
}
u32 alSeqSecToTicks(ALSeq *seq, f32 sec, u32 tempo)
{
return (u32)(((sec * 1000000.0) * seq->division) / tempo);
}
void alSeqNewMarker(ALSeq *seq, ALSeqMarker *m, u32 ticks)
{
ALEvent evt;
u8 *savePtr, *lastPtr;
s32 saveTicks, lastTicks;
s16 saveStatus, lastStatus;
/* does not check that ticks is within bounds */
if (ticks == 0) { /* common case */
m->curPtr = seq->trackStart;
m->lastStatus = 0;
m->lastTicks = 0;
m->curTicks = 0;
return;
} else {
savePtr = seq->curPtr;
saveStatus = seq->lastStatus;
saveTicks = seq->lastTicks;
seq->curPtr = seq->trackStart;
seq->lastStatus = 0;
seq->lastTicks = 0;
do {
lastPtr = seq->curPtr;
lastStatus = seq->lastStatus;
lastTicks = seq->lastTicks;
alSeqNextEvent(seq, &evt);
if (evt.type == AL_SEQ_END_EVT)
{
lastPtr = seq->curPtr;
lastStatus = seq->lastStatus;
lastTicks = seq->lastTicks;
break;
}
} while (seq->lastTicks < ticks);
m->curPtr = lastPtr;
m->lastStatus = lastStatus;
m->lastTicks = lastTicks;
m->curTicks = seq->lastTicks; /* Used by test loop condition. */
seq->curPtr = savePtr;
seq->lastStatus = saveStatus;
seq->lastTicks = saveTicks;
}
}
s32 alSeqGetTicks(ALSeq *seq){
return seq->lastTicks;
}
void alSeqSetLoc(ALSeq *seq, ALSeqMarker *m){
seq->curPtr = m->curPtr;
seq->lastStatus = m->lastStatus;
seq->lastTicks = m->lastTicks;
}
void alSeqGetLoc(ALSeq *seq, ALSeqMarker *m){
m->curPtr = seq->curPtr;
m->lastStatus = seq->lastStatus;
m->lastTicks = seq->lastTicks;
}
/* non-aligned byte reading routines */
static u8 read8(ALSeq *seq)
{
return *seq->curPtr++;
}
static s16 read16(ALSeq *seq)
{
s16 tmp;
tmp = *seq->curPtr++ << 8;
tmp |= *seq->curPtr++;
return tmp;
}
static s32 read32(ALSeq *seq)
{
s32 tmp;
tmp = *seq->curPtr++ << 24;
tmp |= *seq->curPtr++ << 16;
tmp |= *seq->curPtr++ << 8;
tmp |= *seq->curPtr++;
return tmp;
}
static s32 readVarLen(ALSeq *seq)
{
s32 value;
s32 c;
c = *seq->curPtr++;
value = c;
if ( c & 0x80 ) {
value &= 0x7f;
do {
c = *seq->curPtr++;
value = (value << 7) + (c & 0x7f);
} while (c & 0x80);
}
return (value);
}

38
src/core1/done/audio/sl.c Normal file
View File

@@ -0,0 +1,38 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void alInit(ALGlobals *g, ALSynConfig *c){
if (!alGlobals) { /* already initialized? */
alGlobals = g;
alSynNew(&alGlobals->drvr, c);
}
}
void alClose(ALGlobals *glob)
{
if (alGlobals) {
alSynDelete(&glob->drvr);
alGlobals = 0;
}
}
void alLink(ALLink *ln, ALLink *to){
ln->next = to->next;
ln->prev = to;
if (to->next)
to->next->prev = ln;
to->next = ln;
}
void alUnlink(ALLink *ln){
if (ln->next)
ln->next->prev = ln->prev;
if (ln->prev)
ln->prev->next = ln->next;
}

View File

@@ -0,0 +1,12 @@
#include <ultra64.h>
#include "synthInternals.h"
ALFxRef *alSynAllocFX(ALSynth *s, s16 bus, ALSynConfig *c, ALHeap *hp)
{
alFxNew(&s->auxBus[bus].fx[0], c, hp);
alFxParam(&s->auxBus[bus].fx[0], AL_FILTER_SET_SOURCE,
&s->auxBus[bus]);
alMainBusParam(s->mainBus, AL_FILTER_ADD_SOURCE,&s->auxBus[bus].fx[0]);
return (ALFxRef)(&s->auxBus[bus].fx[0]);
}

View File

@@ -0,0 +1,6 @@
#include <ultra64.h>
void alSynDelete(ALSynth *drvr)
{
drvr->head = 0;
}

View File

@@ -0,0 +1,303 @@
#include <ultra64.h>
#include "synthInternals.h"
#ifdef AUD_PROFILE
#include <os.h>
extern u32 cnt_index, drvr_num, drvr_cnt, drvr_max, drvr_min, lastCnt[];
extern u32 client_num, client_cnt, client_max, client_min;
#endif
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef assert
#define assert(s)
#endif
static s32 __nextSampleTime(ALSynth *drvr, ALPlayer **client);
static s32 _timeToSamplesNoRound(ALSynth *ALSynth, s32 micros);
/***********************************************************************
* Synthesis driver public interfaces
***********************************************************************/
void alSynNew(ALSynth *drvr, ALSynConfig *c)
{
s32 i;
ALVoice *vv;
PVoice *pv;
ALVoice *vvoices;
PVoice *pvoices;
ALHeap *hp = c->heap;
ALSave *save;
ALFilter *sources;
ALParam *params;
ALParam *paramPtr;
drvr->head = NULL;
drvr->numPVoices = c->maxPVoices;
drvr->curSamples = 0;
drvr->paramSamples = 0;
drvr->outputRate = c->outputRate;
drvr->maxOutSamples = AL_MAX_RSP_SAMPLES;
drvr->dma = (ALDMANew) c->dmaproc;
save = alHeapAlloc(hp, 1, sizeof(ALSave));
alSaveNew(save);
drvr->outputFilter = (ALFilter *)save;
/*
* allocate and initialize the auxilliary effects bus. at present
* we only support 1 effects bus.
*/
drvr->auxBus = alHeapAlloc(hp, 1, sizeof(ALAuxBus));
drvr->maxAuxBusses = 1;
sources = alHeapAlloc(hp, c->maxPVoices, sizeof(ALFilter *));
alAuxBusNew(drvr->auxBus, sources, c->maxPVoices);
/*
* allocate and initialize the main bus.
*/
drvr->mainBus = alHeapAlloc(hp, 1, sizeof(ALMainBus));
sources = alHeapAlloc(hp, c->maxPVoices, sizeof(ALFilter *));
alMainBusNew(drvr->mainBus, sources, c->maxPVoices);
if (c->fxType != AL_FX_NONE){
/*
* Allocate an effect and set parameters
*/
alSynAllocFX(drvr, 0, c, hp);
} else
/*
* Connect the aux bus to the main bus
*/
alMainBusParam(drvr->mainBus, AL_FILTER_ADD_SOURCE, &drvr->auxBus[0]);
/*
* Build the physical voice lists
*/
drvr->pFreeList.next = 0;
drvr->pFreeList.prev = 0;
drvr->pLameList.next = 0;
drvr->pLameList.prev = 0;
drvr->pAllocList.next = 0;
drvr->pAllocList.prev = 0;
pvoices = alHeapAlloc(hp, c->maxPVoices, sizeof(PVoice));
for (i = 0; i < c->maxPVoices; i++) {
pv = &pvoices[i];
alLink((ALLink *)pv, &drvr->pFreeList);
pv->vvoice = 0;
alLoadNew(&pv->decoder, drvr->dma, hp);
alLoadParam(&pv->decoder, AL_FILTER_SET_SOURCE, 0);
alResampleNew(&pv->resampler, hp);
alResampleParam(&pv->resampler, AL_FILTER_SET_SOURCE, &pv->decoder);
alEnvmixerNew(&pv->envmixer, hp);
alEnvmixerParam(&pv->envmixer, AL_FILTER_SET_SOURCE, &pv->resampler);
alAuxBusParam(drvr->auxBus, AL_FILTER_ADD_SOURCE, &pv->envmixer);
pv->channelKnob = (ALFilter *)&pv->envmixer;
}
alSaveParam(save, AL_FILTER_SET_SOURCE, drvr->mainBus);
/*
* build the parameter update list
*/
params = alHeapAlloc(hp, c->maxUpdates, sizeof(ALParam));
drvr->paramList = 0;
for (i = 0; i < c->maxUpdates; i++) {
paramPtr= &params[i];
paramPtr->next = drvr->paramList;
drvr->paramList = paramPtr;
}
drvr->heap = hp;
}
/*
* slAudioFrame() is called every video frame, and is based on the video
* frame interrupt. It is assumed to be an accurate time source for the
* clients.
*/
Acmd *alAudioFrame(Acmd *cmdList, s32 *cmdLen, s16 *outBuf, s32 outLen)
{
ALPlayer *client;
ALFilter *output;
ALSynth *drvr = &alGlobals->drvr;
s16 tmp = 0; /* Starting buffer in DMEM */
Acmd *cmdlEnd = cmdList;
Acmd *cmdPtr;
s32 nOut;
s16 *lOutBuf = outBuf;
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
if (drvr->head == 0) {
*cmdLen = 0;
return cmdList; /* nothing to do */
}
/*
* run down list of clients and execute callback if needed this
* subframe. Here we do all the work for the frame at the
* start. Time offsets that occur before the next frame are
* executed "early".
*/
#ifdef AUD_PROFILE
lastCnt[++cnt_index] = osGetCount();
#endif
/*
* paramSamples = time of next parameter change.
* curSamples = current sample time.
* so paramSamples - curSamples is the time until the next parameter change.
* if the next parameter change occurs within this frame time (outLen),
* then call back the client that contains the parameter change.
* Note, paramSamples must be rounded down to 16 sample boundary for use
* during the client handler.
*/
for (drvr->paramSamples = __nextSampleTime(drvr, &client);
drvr->paramSamples - drvr->curSamples < outLen;
drvr->paramSamples = __nextSampleTime(drvr, &client))
{
drvr->paramSamples &= ~0xf;
client->samplesLeft += _timeToSamplesNoRound(drvr, (*client->handler)(client));
}
/* for safety's sake, always store paramSamples aligned to 16 sample boundary.
* this way, if an voice handler routine gets called outside the ALVoiceHandler
* routine (alSynAllocVoice) it will get timestamped with an aligned value and
* will be processed immediately next audio frame.
*/
drvr->paramSamples &= ~0xf;
#ifdef AUD_PROFILE
PROFILE_AUD(client_num, client_cnt, client_max, client_min);
#endif
/*
* Now build the command list in small chunks
*/
while (outLen > 0){
nOut = MIN(drvr->maxOutSamples, outLen);
/*
* construct the command list for each physical voice by calling
* the head of the filter chain.
*/
cmdPtr = cmdlEnd;
aSegment(cmdPtr++, 0, 0);
output = drvr->outputFilter;
(*output->setParam)(output, AL_FILTER_SET_DRAM, lOutBuf);
cmdlEnd = (*output->handler)(output, &tmp, nOut, drvr->curSamples,
cmdPtr);
outLen -= nOut;
lOutBuf += nOut<<1; /* For Stereo */
drvr->curSamples += nOut;
}
*cmdLen = (s32) (cmdlEnd - cmdList);
_collectPVoices(drvr); /* collect free physical voices */
#ifdef AUD_PROFILE
PROFILE_AUD(drvr_num, drvr_cnt, drvr_max, drvr_min);
#endif
return cmdlEnd;
}
/***********************************************************************
* Synthesis driver private interfaces
***********************************************************************/
ALParam *__allocParam()
{
ALParam *update = 0;
ALSynth *drvr = &alGlobals->drvr;
if (drvr->paramList) {
update = drvr->paramList;
drvr->paramList = drvr->paramList->next;
update->next = 0;
}
return update;
}
void __freeParam(ALParam *param)
{
ALSynth *drvr = &alGlobals->drvr;
param->next = drvr->paramList;
drvr->paramList = param;
}
void _collectPVoices(ALSynth *drvr)
{
ALLink *dl;
PVoice *pv;
while ((dl = drvr->pLameList.next) != 0) {
pv = (PVoice *)dl;
/* ### remove from mixer */
alUnlink(dl);
alLink(dl, &drvr->pFreeList);
}
}
void _freePVoice(ALSynth *drvr, PVoice *pvoice)
{
/*
* move the voice from the allocated list to the lame list
*/
alUnlink((ALLink *)pvoice);
alLink((ALLink *)pvoice, &drvr->pLameList);
}
/*
Add 0.5 to adjust the average affect of
the truncation error produced by casting
a float to an int.
*/
s32 _timeToSamplesNoRound(ALSynth *synth, s32 micros)
{
f32 tmp = ((f32)micros) * synth->outputRate / 1000000.0 + 0.5;
return (s32)tmp;
}
s32 _timeToSamples(ALSynth *synth, s32 micros)
{
return _timeToSamplesNoRound(synth, micros) & ~0xf;
}
static s32 __nextSampleTime(ALSynth *drvr, ALPlayer **client)
{
ALMicroTime delta = 0x7fffffff; /* max delta for s32 */
ALPlayer *cl;
assert(drvr->head);
*client = 0;
for (cl = drvr->head; cl != 0; cl = cl->next) {
if ((cl->samplesLeft - drvr->curSamples) < delta) {
*client = cl;
delta = cl->samplesLeft - drvr->curSamples;
}
}
return (*client)->samplesLeft;
}

View File

@@ -0,0 +1,15 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void func_8025AFB0(void) {}
void func_8025AFB8(void) {}
void func_8025AFC0(Gfx **arg0, Mtx **arg1, Vtx **arg2) {}
s32 func_8025AFD0(void)
{
return 0;
}

133
src/core1/done/code_1E360.c Normal file
View File

@@ -0,0 +1,133 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "SnS.h"
/**
* An index used to track the position in the incoming payload
* we should read the next key from.
*/
extern s32 snsPayloadInCurrPos;
/**
* An index used to track the position in the outgoing payload
* it should write the next key to.
*/
extern s32 snsPayloadOutCurrPos;
struct SnsPayload *snspayload_init_new_payload(struct SnsPayload *payload)
{
u32 i;
payload->magic = SNS_HEADER_MAGIC;
for (i = 0; i < SNS_PAYLOAD_DATALEN; i++)
payload->data[i] = 0;
payload->pad = 0;
snspayload_calc_checksum(payload);
return payload;
}
void snspayload_set_key_at_idx(struct SnsPayload *payload, s32 idx, s32 key)
{
payload->data[idx] = key;
snspayload_calc_checksum(payload);
}
void snspayload_calc_checksum(struct SnsPayload *payload)
{
glcrc_calc_checksum(payload, &payload->checksum, payload->checksum);
}
bool snspayload_validate(struct SnsPayload *payload)
{
u32 checksum[2];
glcrc_calc_checksum(payload, payload->checksum, checksum);
if ((payload->checksum[0] == checksum[0]) && (payload->checksum[1] == checksum[1]))
return TRUE;
return FALSE;
}
struct SnsPayload *snspayload_find_payload_in_ram(void)
{
struct SnsPayload *payload;
for (payload = (struct SnsPayload *)0x80000000; payload < (struct SnsPayload *)0x80400080; payload++)
if (payload->magic == SNS_HEADER_MAGIC && snspayload_validate(payload))
return payload;
return NULL;
}
s32 snspayload_contains_key(struct SnsPayload *payload, s32 key)
{
u32 i;
for (i = 0; i < SNS_PAYLOAD_DATALEN; i++)
if (payload->data[i] == key)
return key;
return 0;
}
s32 snspayload_get_key_in_range(struct SnsPayload *payload, s32 min, s32 max)
{
s32 i;
for (i = 0; i < SNS_PAYLOAD_DATALEN; i++)
{
if (payload->data[i] < min)
continue;
if (payload->data[i] > max)
continue;
return payload->data[i];
}
return 0;
}
void snspayload_rewind_incoming(void)
{
snsPayloadInCurrPos = 0;
}
u32 snspayload_get_next_key(struct SnsPayload *payload)
{
while (snsPayloadInCurrPos < SNS_PAYLOAD_DATALEN)
{
if (payload->data[snsPayloadInCurrPos])
return payload->data[snsPayloadInCurrPos++];
snsPayloadInCurrPos++;
}
return 0;
}
void snspayload_rewind_outgoing(void)
{
snsPayloadOutCurrPos = 0;
}
void snspayload_append_key_to_outgoing_payload(struct SnsPayload *payload, s32 key)
{
payload->data[snsPayloadOutCurrPos++] = key;
}
void snspayload_finalise_outgoing_payload(struct SnsPayload *payload)
{
while (snsPayloadOutCurrPos < SNS_PAYLOAD_DATALEN)
payload->data[snsPayloadOutCurrPos++] = 0;
snspayload_calc_checksum(payload);
}

View File

@@ -0,0 +1,36 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "n_libaudio.h"
extern N_ALSynth *D_80276E80;
extern N_ALSynth *D_80276E84;
void func_8025C2E0(s32 a0)
{
if (D_80276E80)
{
func_8025F610();
D_80276E80 = NULL;
D_80276E84 = NULL;
}
}
void func_8025C320(N_ALSynth *synth, ALSynConfig *config)
{
if (D_80276E80 != NULL)
return;
D_80276E80 = synth;
if (D_80276E84 != NULL)
return;
D_80276E84 = synth;
n_alSynNew(config);
}

651
src/core1/done/code_CE60.c Normal file
View File

@@ -0,0 +1,651 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "SnS.h"
typedef struct {
s16 x_min;
s16 x_max;
s16 y_min;
s16 y_max;
s16 z_min;
s16 z_max;
} Struct_Core1_CE60_0s;
void func_80250530(s32, u16 chan_mask, f32);
/* .data */
extern s32 D_80275C10;
extern s32 D_80275C14;
extern u8 D_80275C18;
extern u8 D_80275C1C;
extern Struct_Core1_CE60_0s D_80275C20[];
/* .bss */
s32 D_802806F0;
int D_802806F4;
s32 D_802806F8[4];
s32 D_80280708[4];
/* .code */
void func_8024A880(s32 chan_mask){
func_80250530(0, chan_mask, 3.0f);
}
void func_8024A8AC(s32 chan_mask, f32 arg1){
func_80250530(0, chan_mask, arg1);
}
int func_8024A8DC(s32 arg0, s32 arg1, s32 arg2){
return (arg0 - D_802806F8[0])*(arg0 - D_802806F8[0]) + (arg1 - D_802806F8[2])*(arg1 - D_802806F8[2]) < arg2*arg2;
}
f32 func_8024A928(f32 arg0, f32 arg1){
return gu_sqrtf((arg0 - D_802806F8[0])*(arg0 - D_802806F8[0]) + (arg1 - D_802806F8[2])*(arg1 - D_802806F8[2]));
}
int func_8024A984(s32 arg0){
func_802585E0(D_802806F8, D_80275C20[arg0].x_min, D_80275C20[arg0].y_min, D_80275C20[arg0].z_min, D_80275C20[arg0].x_max, D_80275C20[arg0].y_max, D_80275C20[arg0].z_max);
}
void func_8024A9EC(s32 arg0){
if(!func_8025ADBC(D_80280708[0]) && D_80280708[2]){
func_8025A104(D_80280708[0], 0);
}
func_8025A55C(D_80280708[2], arg0 ? arg0 : 0x1f4, 4 );
if(func_8025AD7C(D_80280708[1]) || D_80280708[3]){
func_8025ABB8(D_80280708[1], D_80280708[3], arg0 ? arg0 : 0x1f4, 4 );
}//L8024AA94
func_8025A864(D_80280708[1]);
}
void func_8024AAB0(void){
f32 plyr_pos[3]; //sp34
f32 sp30;
func_8028EB3C(&D_802806F8);
player_getPosition(plyr_pos);
D_80280708[0] = func_8032274C();
D_80280708[1] = func_80322758();
D_80280708[2] = D_80280708[3] = 0;
if(0 <= D_80280708[0])
D_80280708[2] = func_80250034(D_80280708[0]);
if(0 <= D_80280708[1])
D_80280708[3] = func_80250034(D_80280708[1]);
switch(map_get()){
case MAP_7_TTC_TREASURE_TROVE_COVE: //L8024ABA8
D_80280708[2] = ml_map_f(4700 - D_802806F8[1], 0.0f, 900.0f, 0.0f, D_80280708[2]);
D_80280708[3] = ml_map_f(4700 - D_802806F8[1], 0.0f, 900.0f, D_80280708[3], 0.0f);
break;
case MAP_B_CC_CLANKERS_CAVERN: //
sp30 = func_8024A928(13909.0f, -26.0f);
D_80280708[2] = ml_map_f(sp30, 1500.0f, 1800.0f, 0.0f, D_80280708[2]);
D_80280708[3] = ml_map_f(sp30, 1500.0f, 1800.0f, D_80280708[3], 0.0f);
break;
case MAP_1_SM_SPIRAL_MOUNTAIN: //L8024ACC4
if(func_8024A984(4))
D_80280708[2] = 0;
else
D_80280708[3] = 0;
break;
case MAP_1B_MMM_MAD_MONSTER_MANSION: //L8024ACE4
if(func_80309D58(plyr_pos, 1)){
D_80280708[2] = 0;
}
else{
D_80280708[3] = 0;
}
break;
case MAP_41_FP_BOGGYS_IGLOO: //L8024AD08
if( jiggyscore_isCollected(JIGGY_2E_FP_PRESENTS)
|| (levelSpecificFlags_get(0x11) && levelSpecificFlags_get(0x12) && levelSpecificFlags_get(0x13))
){
D_80280708[2] = 0;
}
else{
D_80280708[3] = 0;
}
break;
case MAP_1D_MMM_CELLAR: //L8024AD58
if(sns_get_item_state(SNS_ITEM_EGG_CYAN, 1) && D_802806F8[0] >= 0x23A){
D_80280708[2] = 0;
}
else{
D_80280708[3] = 0;
}
break;
case MAP_7F_FP_WOZZAS_CAVE: //L8024AD8C
if(sns_get_item_state(SNS_ITEM_ICE_KEY, 1) && func_8024A8DC(0x619, 0x97a, 0x69a)){
D_80280708[2] = 0;
}
else{
D_80280708[3] = 0;
}
break;
case MAP_45_CCW_AUTUMN: //L8024ADC0
case MAP_46_CCW_WINTER: //L8024ADC0
if(func_8024A984(5)){
D_80280708[2] = 0;
}
else{
D_80280708[3] = 0;
}
break;
}//L8024ADE0
}
void func_8024ADF0(s32 arg0){
func_8024AAB0();
if(arg0)
func_8025A9D4();
if(0 < D_80280708[0] && 0 < D_80280708[2])
func_8025A104(D_80280708[0], D_80280708[2]);
if(0 < D_80280708[1] && 0 < D_80280708[3])
func_8025A6CC(D_80280708[1], D_80280708[3]);
}
void func_8024AE74(void){
D_802806F0 = 0;
D_80275C10 = -1;
D_80275C14 = 0;
D_80275C1C = D_80275C18 = func_8024A8DC(0xb43, -0x2918, 0x1950) ? 1 : 0;
}
void func_8024AED8(void){
D_80275C10 = -1;
D_80275C14 = 0;
D_80275C18 = 0;
D_80275C1C = 0;
}
void func_8024AF00(s32 arg0, s32 arg1){
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(arg0);
}
else{
func_8024A880(arg1);
}
}
void func_8024AF48(void){
if(!D_802806F4) return;
if(func_803203FC(1)) return;
if(func_803203FC(0x1f)) return;
if(func_802D686C()) return;
if(func_8028F22C()) return;
if(gctransition_8030BDC0()) return;
if(getGameMode() == GAME_MODE_A_SNS_PICTURE) return;
func_8028EB3C(D_802806F8);
func_8024AAB0();
switch(map_get()){
case MAP_2_MM_MUMBOS_MOUNTAIN: // L8024B000
if(func_8024A8DC(-4450, 4550, 1900) ||func_8024A8DC(-0x1777, 0x1820, 0x26c)){
func_8024A880(0x1cc0);
}
else if(func_8024A8DC(0x119F, -0x760, 0x7d0)){
func_8024A880(0xb0c0);
}
else if(func_8024A8DC(0x12c, -0x35a, 0x898)){
func_8024A880(0x513f);
}
else{
func_8024AF00(0x200, 0x103f);
}
break;
case MAP_7_TTC_TREASURE_TROVE_COVE: // L8024B094
func_8024A9EC(0);
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x600);
}
else if(func_8024A8DC(-0x12C, 0x58c, 0x866)
|| (func_8024A8DC(-0x12c, 0x58c, 0xc1c)
&& D_802806F8[1] < 0x514
&& !func_8024A8DC(-0x49, 0x2c43, 0x1c0c)
&& !func_8024A8DC(0x6c8, 0xe04, 0x1c7)
&& !func_8024A8DC(0x564, 0xf9a, 0x190)
)
){
func_8024A880(0x7800);
}
else{
func_8024A880(0x60ff);
}
break;
case MAP_B_CC_CLANKERS_CAVERN: // L8024B158
func_8024A9EC(0);
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
if(!(D_802806F8[1] < 0x28b)){
func_8024A8AC(0x8180, 5.0f);
}
else{
func_8024A8AC(0x3e00, 5.0f);
}
}
else{
func_8024A880(0x407f);
}
break;
case MAP_12_GV_GOBIS_VALLEY:// L8024B1BC
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x8020);
}
else if(func_8024A8DC(-0xf96, 0x1626, 0xe74)){
func_8024A880(0x797f);
}
else{
func_8024A880(0x67fe);
}
break;
case MAP_3_UNUSED: // L8024B214
func_8024AF00(0x1800, 0x67fe);
break;
case MAP_5_TTC_BLUBBERS_SHIP: // L8024B228
func_8024AF00(0x600, 0x7800);
break;
case MAP_1_SM_SPIRAL_MOUNTAIN: // L8024B23C
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x9000);
}
else{
if(func_802DA498())
func_8024A9EC(0);
func_8024A880(0x6fff);
}
break;
case MAP_21_CC_WITCH_SWITCH_ROOM:// L8024B288
case MAP_22_CC_INSIDE_CLANKER:// L8024B288
case MAP_23_CC_GOLDFEATHER_ROOM:// L8024B288
func_8024AF00(0x3c00, 0x61ff);
break;
case MAP_25_MMM_WELL:// L8024B29C
case MAP_2F_MMM_WATERDRAIN_BARREL:// L8024B29C
func_8024AF00(0x1000, 0xcfff);
break;
case MAP_13_GV_MEMORY_GAME:// L8024B2B0
case MAP_14_GV_SANDYBUTTS_MAZE:// L8024B2B0
case MAP_15_GV_WATER_PYRAMID:// L8024B2B0
case MAP_16_GV_RUBEES_CHAMBER:// L8024B2B0
case MAP_1A_GV_INSIDE_JINXY:// L8024B2B0
func_8024AF00(0x3ffe, 0x4ffe);
break;
case MAP_1B_MMM_MAD_MONSTER_MANSION:// L8024B2C4
if( !mapSpecificFlags_get(1)
&& !func_8025AD7C(COMUSIC_4_MMM_CLOCK_VERSION)
&& !func_8025AD7C(COMUSIC_3C_MINIGAME_LOSS)
){
func_8024A9EC(0);
}
func_8024A880((mapSpecificFlags_get(1) ? 0x2000: 0) + 0xcfff);
break;
case MAP_D_BGS_BUBBLEGLOOP_SWAMP: // L8024B328
if( func_8024A8DC(0x762, -0x542, 0x578)
|| func_8024A8DC(-0x85, 0x7d8, 0x384)
|| func_8024A8DC(-0xe2d, -0x217, 0x578)
){
func_8024A8AC(0x2f4f, 2.0f);
}
else{
func_8024A8AC(0x6f4f, 2.0f);
}
break;
case MAP_31_RBB_RUSTY_BUCKET_BAY:// L8024B38C
if( (-4200 <= D_802806F8[0] && D_802806F8[0] < -3700)
&& (-900 <= D_802806F8[2] && D_802806F8[2] < 900)
){
func_8024A880(0x51ff);
}
else{
func_8024AF00(0x800, 0x71bf);
}
break;
case MAP_35_RBB_WAREHOUSE:// L8024B3E8
case MAP_36_RBB_BOATHOUSE:// L8024B3E8
case MAP_37_RBB_CONTAINER_1:// L8024B3E8
case MAP_38_RBB_CONTAINER_3:// L8024B3E8
case MAP_3E_RBB_CONTAINER_2:// L8024B3E8
func_8024AF00(0x800, 0xfe);
break;
case MAP_40_CCW_HUB:// L8024B3FC
if(func_8024A8DC(0, 0, 0x802)){
func_8024A8AC(7, 2.0f);
}
else if(0x5aa <= D_802806F8[2]){
func_8024A8AC(0x407, 2.0f);
}
else if(D_802806F8[0] < -0x5a9){
func_8024A8AC(0x707, 2.0f);
}
else if(D_802806F8[2] < -0x5a9){
func_8024A8AC(0x1067, 2.0f);
}
else if(0x5aa <= D_802806F8[0]) {
func_8024A8AC(0x7007, 2.0f);
}
break;
case MAP_A_TTC_SANDCASTLE: // L8024B4AC
func_8024AF00(0xCE, 0x3C);
break;
case MAP_43_CCW_SPRING:// L8024B4C0
func_8024AF00(0x400, 0x7bbf);
break;
case MAP_45_CCW_AUTUMN:// L8024B4D4
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x600);
}
else{
func_8024A9EC(0);
func_8024A880(0x7BEF);
}
break;
case MAP_54_UNUSED:// L8024B510
case MAP_55_UNUSED:// L8024B510
case MAP_57_UNUSED:// L8024B510
case MAP_58_UNUSED:// L8024B510
case MAP_59_UNUSED:// L8024B510
func_8024AF00(0xc, 0x307b);
break;
case MAP_56_UNUSED:// L8024B524
func_8024AF00(0x10, 0x4f6f);
break;
case MAP_27_FP_FREEZEEZY_PEAK:// L8024B538
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x400);
}
else if( mapSpecificFlags_get(0) && !jiggyscore_isCollected(JIGGY_2F_FP_XMAS_TREE)){
func_8024A880(0x4bff);
}
else{
func_8024A880(0x43ff);
}
break;
case MAP_65_CCW_SPRING_WHIPCRACK_ROOM:// L8024B59C
func_8024A880(0x107);
break;
case MAP_66_CCW_SUMMER_WHIPCRACK_ROOM:// L8024B5AC
func_8024A880(0x1C7);
break;
case MAP_67_CCW_AUTUMN_WHIPCRACK_ROOM:// L8024B5BC
func_8024A880(0xC07);
break;
case MAP_68_CCW_WINTER_WHIPCRACK_ROOM:// L8024B5CC
func_8024A880(0x1407);
break;
case MAP_5E_CCW_SPRING_NABNUTS_HOUSE:// L8024B5DC
func_8024A880(0x41fe);
break;
case MAP_5F_CCW_SUMMER_NABNUTS_HOUSE:// L8024B5EC
func_8024A880(0x71fe);
break;
case MAP_60_CCW_AUTUMN_NABNUTS_HOUSE:// L8024B5FC
func_8024A880(0x7fe);
break;
case MAP_61_CCW_WINTER_NABNUTS_HOUSE:// L8024B60C
func_8024A880(0xbfe);
break;
case MAP_63_CCW_AUTUMN_NABNUTS_WATER_SUPPLY:// L8024B61C
func_8024AF00(1, 0x7fe);
break;
case MAP_64_CCW_WINTER_NABNUTS_WATER_SUPPLY:// L8024B630
func_8024AF00(1, 0xbfe);
break;
case MAP_69_GL_MM_LOBBY:// L8024B644
if(func_8024A8DC(0xdb6, -0x65e, 0x4e2))
func_8024A880(0x7c00);
else
func_8024A880(0x41ff);
break;
case MAP_6A_GL_TTC_AND_CC_PUZZLE:// L8024B67C
if(0x2b8 <= D_802806F8[1] && func_8024A8DC(-0x615, -0x389, 0x1dd)){
func_8024A880(0x8e40);
}
else if(func_8024A8DC(0x5dc, -0x37a, 0x226) || func_8024A8DC(0x754, -0x453, 0x172)){
func_8024A880(0xf040);
}
else{
func_8024A880(0x81ff);
}
break;
case MAP_6B_GL_180_NOTE_DOOR:// L8024B704
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x8800);
}
else if(func_8024A8DC(0x10eb, 0x4f5, 0x730)) {
func_8024A880(0x8640);
}
else if(func_8024A8DC(-0x526, 0x777, 0x125) || func_8024A8DC(-0x515, 0x878, 0xea)){
func_8024A880(0xf000);
}else{
func_8024A880(0x81bf);
}
break;
case MAP_6C_GL_RED_CAULDRON_ROOM:// L8024B794
func_8024A880(0x81bf);
break;
case MAP_6D_GL_TTC_LOBBY:// L8024B7A4
func_8024A880(0xf000);
break;
case MAP_70_GL_CC_LOBBY:// L8024B7B4
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x8100);
}
else if(func_8024A8DC(-0x19d6, -0x1d3, 0x71e)){
func_8024A880(0xf047);
}
else{
func_8024A880(0x8e41);
}
break;
case MAP_6E_GL_GV_LOBBY:// L8024B80C
if(func_8024A8DC(0, -0x1996, 0xe42)){
func_8024A880(0xfe00);
}
else{
func_8024A880(0x81ff);
}
break;
case MAP_6F_GL_FP_LOBBY:// L8024B844
if(0xe75 <= D_802806F8[2]){
func_8024A880(0xe040);
}
else{
func_8024A880(0x81bf);
}
break;
case MAP_74_GL_GV_PUZZLE:// L8024B878
if(func_8024A8DC(-0xa49, -0x1f, 0x203)){
func_8024A880(0xe600);
}
else{
func_8024A880(0x81ff);
}
break;
case MAP_75_GL_MMM_LOBBY:// L8024B8B0
case MAP_7A_GL_CRYPT:// L8024B8B0
func_8024A880(0xd800);
break;
case MAP_71_GL_STATUE_ROOM:// L8024B8C0
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x200);
}
else if(func_8024A8DC(-0xf0e, -0x15a, 0x302)){
func_8024A880(0x9c00);
}
else{
func_8024A880(0x81bf);
}
break;
case MAP_72_GL_BGS_LOBBY:// L8024B918
if(D_80275C10 == -1 && D_80275C18 == 0){
D_80275C10 = func_802F9AA8(0x410);
func_802F9F80(D_80275C10, 3.0f, 16777216.0f, 0.0f);
func_802FA060(D_80275C10, 3500, 3500, 0.0f);
D_80275C14 = func_802F9AA8(0x411);
func_802F9F80(D_80275C14, 3.0f, 16777216.0f, 0.0f);
func_802FA060(D_80275C14, 3500, 3500, 0.0f);
}//L8024B9BC
if(D_80275C1C != D_80275C18){
D_80275C1C = D_80275C18;
if(D_80275C18){
func_802F9FD0(D_80275C10, 0.0f, 0.0f, 3.0f);
func_802F9FD0(D_80275C14, 0.0f, 0.0f, 3.0f);
D_80275C10 = -1;
D_80275C14 = 0;
}
}//L8024BA2C
if(func_8024A8DC(0xb43, -0x2918, 0x1950)){
D_80275C18 = 1;
func_8024A880(0xe040);
}
else{
D_80275C18 = 0;
func_8024A880(0x9c00);
}
break;
case MAP_76_GL_640_NOTE_DOOR:// L8024BA70
func_8024AF00(0x8200, 0x81bf);
break;
case MAP_77_GL_RBB_LOBBY:// L8024BA84
func_8024AF00(0x8200, 0xf000);
break;
case MAP_78_GL_RBB_AND_MMM_PUZZLE:// L8024BA98
if(func_8028EE84() == BSWATERGROUP_2_UNDERWATER){
func_8024A880(0x8200);
}
else if(0x15a <= D_802806F8[1] && func_8024A8DC(-0x89a, 0x21a, 0x368)){
func_8024A880(0x8C00);
}
else if(func_8024A8DC(-0x36, 0x14, 0xa5c)){
func_8024A880(0x81bf);
}
else{
func_8024A880(0xf000);
}
break;
case MAP_79_GL_CCW_LOBBY:// L8024BB2C
if(0x31c <= D_802806F8[1] && D_802806F8[1] < 0x44c && func_8024A8DC(0x1c, 0x11c9, 0x431))
func_8024A880(0x81bf);
else if(-4 <= D_802806F8[1] && D_802806F8[1] < 0x168 && func_8024A8DC(0x87, 0x1373, 0x86c))
func_8024A880(0x81bf);
else
func_8024A880(0x9e00);
break;
case MAP_80_GL_FF_ENTRANCE:// L8024BBBC
if(D_802806F8[2] < 0x4e2)
func_8024A880(0xe040);
else
func_8024A880(0x9e00);
break;
case MAP_7F_FP_WOZZAS_CAVE:// L8024BBF0
func_8024A9EC((sns_get_item_state(SNS_ITEM_ICE_KEY, 1) && func_8024A8DC(0x619, 0x97a, 0x69a))? 0x7ff8 : 0);
func_8024AF00(0x20, 0x1f);
break;
case MAP_8B_RBB_ANCHOR_ROOM:// L8024BC40
func_8024AF00(0x800, 0x51ff);
break;
case MAP_34_RBB_ENGINE_ROOM:// L8024BC54
func_8024AF00(0x800, 0x43fe);
break;
case MAP_91_FILE_SELECT:// L8024BC68
if(!func_802C5A30()){
func_8024A8AC(0x200, 0.5f);
}
else{
func_8024A8AC(0x1ff, 0.5f);
}
break;
case MAP_8C_SM_BANJOS_HOUSE:// L8024BC9C
func_8024A8AC(0x1ff, 0.5f);
break;
case MAP_1D_MMM_CELLAR:// L8024BCB0
func_8024A9EC((sns_get_item_state(SNS_ITEM_EGG_CYAN, 1) && !(D_802806F8[0] < 0x23a))? 0x7ff8 : 0);
break;
case MAP_46_CCW_WINTER:// L8024BCF0
func_8024A9EC(0);
break;
}//L8024BCF8
}
void func_8024BD08(s32 arg0){
if(arg0){
D_802806F0++;
}
else{
D_802806F0--;
}
}
void func_8024BD40(s32 arg0, s32 arg1){
if(arg1 == 3){
}
else{
if(arg1 == 2){
D_802806F4 = TRUE;
}
else{
D_802806F4 = FALSE;
}
}
}

42
src/core1/done/gu/guint.h Normal file
View File

@@ -0,0 +1,42 @@
/**************************************************************************
* *
* Copyright (C) 1994, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#include "mbi.h"
#include "gu.h"
typedef union
{
struct
{
unsigned int hi;
unsigned int lo;
} word;
double d;
} du;
typedef union
{
unsigned int i;
float f;
} fu;
#ifndef __GL_GL_H__
typedef float Matrix[4][4];
#endif
#define ROUND(d) (int)(((d) >= 0.0) ? ((d) + 0.5) : ((d) - 0.5))
#define ABS(d) ((d) > 0) ? (d) : -(d)
extern float __libm_qnan_f;

View File

@@ -0,0 +1,15 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void guNormalize(float *x, float *y, float *z)
{
float m;
m = gu_sqrtf((*x)*(*x) + (*y)*(*y) + (*z)*(*z));
m = (f32)1.0/ m;
*x *= m;
*y *= m;
*z *= m;
}

31
src/core1/done/gu/ortho.c Normal file
View File

@@ -0,0 +1,31 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void guOrthoF(float mf[4][4], float l, float r, float b, float t, float n, float f, float scale)
{
int i, j;
guMtxIdentF(mf);
mf[0][0] = 2/(r-l);
mf[1][1] = 2/(t-b);
mf[2][2] = -2/(f-n);
mf[3][0] = -(r+l)/(r-l);
mf[3][1] = -(t+b)/(t-b);
mf[3][2] = -(f+n)/(f-n);
mf[3][3] = 1;
for (i=0; i<4; i++)
for (j=0; j<4; j++)
mf[i][j] *= scale;
}
void guOrtho(Mtx *m, float l, float r, float b, float t, float n, float f, float scale)
{
float mf[4][4];
guOrthoF(mf, l, r, b, t, n, f, scale);
guMtxF2L(mf, m);
}

157
src/core1/done/gu/sinf.c Normal file
View File

@@ -0,0 +1,157 @@
/**************************************************************************
* *
* Copyright (C) 1994, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#include "guint.h"
/* ====================================================================
* ====================================================================
*
* Module: fsin.c
* $Revision: 1.2 $
* $Date: 1995/07/12 17:48:01 $
* $Author: jeffd $
* $Source: /disk6/Master/cvsmdev2/PR/libultra/gu/sinf.c,v $
*
* Revision history:
* 09-Jun-93 - Original Version
*
* Description: source code for fsin function
*
* ====================================================================
* ====================================================================
*/
#pragma weak fsin = __sinf
#pragma weak sinf = __sinf
#define fsin __sinf
/* coefficients for polynomial approximation of sin on +/- pi/2 */
static const du P[] =
{
{0x3ff00000, 0x00000000},
{0xbfc55554, 0xbc83656d},
{0x3f8110ed, 0x3804c2a0},
{0xbf29f6ff, 0xeea56814},
{0x3ec5dbdf, 0x0e314bfe},
};
static const du rpi =
{0x3fd45f30, 0x6dc9c883};
static const du pihi =
{0x400921fb, 0x50000000};
static const du pilo =
{0x3e6110b4, 0x611a6263};
static const fu zero = {0x00000000};
/* ====================================================================
*
* FunctionName fsin
*
* Description computes sine of arg
*
* ====================================================================
*/
float
sinf( float x )
{
double dx, xsq, poly;
double dn;
int n;
double result;
int ix, xpt;
ix = *(int *)&x;
xpt = (ix >> 22);
xpt &= 0x1ff;
/* xpt is exponent(x) + 1 bit of mantissa */
if ( xpt < 0xff )
{
/* |x| < 1.5 */
dx = x;
if ( xpt >= 0xe6 )
{
/* |x| >= 2^(-12) */
/* compute sin(x) with a standard polynomial approximation */
xsq = dx*dx;
poly = ((P[4].d*xsq + P[3].d)*xsq + P[2].d)*xsq + P[1].d;
result = dx + (dx*xsq)*poly;
return ( (float)result );
}
return ( x );
}
if ( xpt < 0x136 )
{
/* |x| < 2^28 */
dx = x;
/* reduce argument to +/- pi/2 */
dn = dx*rpi.d;
n = ROUND(dn);
dn = n;
dx = dx - dn*pihi.d;
dx = dx - dn*pilo.d; /* dx = x - n*pi */
/* compute sin(dx) as before, negating result if n is odd
*/
xsq = dx*dx;
poly = ((P[4].d*xsq + P[3].d)*xsq + P[2].d)*xsq + P[1].d;
result = dx + (dx*xsq)*poly;
if ( (n & 1) == 0 )
return ( (float)result );
return ( -(float)result );
}
if ( x != x )
{
/* x is a NaN; return a quiet NaN */
#ifdef _IP_NAN_SETS_ERRNO
*__errnoaddr = EDOM;
#endif
return ( __libm_qnan_f );
}
/* just give up and return 0.0 */
return ( zero.f );
}

View File

@@ -0,0 +1,8 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
float gu_sqrtf(float val){
return sqrtf(val);
}

View File

@@ -0,0 +1,22 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
void guTranslateF(float mf[4][4], float x, float y, float z)
{
guMtxIdentF(mf);
mf[3][0] = x;
mf[3][1] = y;
mf[3][2] = z;
}
void guTranslate(Mtx *m, float x, float y, float z)
{
float mf[4][4];
guTranslateF(mf, x, y, z);
guMtxF2L(mf, m);
}

12
src/core1/done/io/ai.c Normal file
View File

@@ -0,0 +1,12 @@
#include <os_internal.h>
#include <rcp.h>
s32 __osAiDeviceBusy(void)
{
register s32 status = IO_READ(AI_STATUS_REG);
if (status & AI_STATUS_FIFO_FULL)
return 1;
return 0;
}

View File

@@ -0,0 +1,6 @@
#include <rcp.h>
u32 osAiGetLength(void)
{
return IO_READ(AI_LEN_REG);
}

View File

@@ -0,0 +1,20 @@
#include <rcp.h>
#include "osint.h"
s32 osAiSetFrequency(u32 frequency)
{
register unsigned int dacRate;
register int bitRate;
register float f;
f = osViClock / (float)frequency + .5f;
dacRate = f;
if (dacRate < AI_MIN_DAC_RATE)
return -1;
bitRate = (dacRate / 66) & 0xFF;
if (bitRate > AI_MAX_BIT_RATE)
bitRate = AI_MAX_BIT_RATE;
IO_WRITE(AI_DACRATE_REG, dacRate - 1);
IO_WRITE(AI_BITRATE_REG, bitRate - 1);
IO_WRITE(AI_CONTROL_REG, AI_CONTROL_DMA_ON);
return osViClock / (s32)dacRate;
}

View File

@@ -0,0 +1,23 @@
#include <os_internal.h>
#include <rcp.h>
#include "osint.h"
s32 osAiSetNextBuffer(void *bufPtr, u32 size)
{
static u8 hdwrBugFlag = 0;
char *bptr = bufPtr;
if (hdwrBugFlag != 0)
bptr -= 0x2000;
if ((((u32)bufPtr + size) & 0x3fff) == 0x2000)
hdwrBugFlag = 1;
else
hdwrBugFlag = 0;
if (__osAiDeviceBusy())
return -1;
IO_WRITE(AI_DRAM_ADDR_REG, osVirtualToPhysical(bptr));
IO_WRITE(AI_LEN_REG, size);
return 0;
}

View File

@@ -0,0 +1,36 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
extern OSPiHandle *__osPiTable;
OSPiHandle CartRomHandle;
OSPiHandle *osCartRomInit(void)
{
u32 domain;
u32 saveMask;
domain = 0;
if (CartRomHandle.baseAddress == PHYS_TO_K1(PI_DOM1_ADDR2))
return &CartRomHandle;
CartRomHandle.type = DEVICE_TYPE_CART;
CartRomHandle.baseAddress = PHYS_TO_K1(PI_DOM1_ADDR2);
osPiRawReadIo(NULL, &domain);
CartRomHandle.latency = domain & 0xff;
CartRomHandle.pulse = (domain >> 8) & 0xff;
CartRomHandle.pageSize = (domain >> 0x10) & 0xf;
CartRomHandle.relDuration = (domain >> 0x14) & 0xf;
CartRomHandle.domain = PI_DOMAIN1;
CartRomHandle.speed = 0;
bzero(&CartRomHandle.transferInfo, sizeof(__OSTranxInfo));
saveMask = __osDisableInt();
CartRomHandle.next = __osPiTable;
__osPiTable = &CartRomHandle;
__osRestoreInt(saveMask);
return &CartRomHandle;
}//*/

View File

@@ -0,0 +1,15 @@
#include <os_internal.h>
#include "controller.h"
s32 osEepromLongRead(OSMesgQueue *mq, u8 address, u8 *buffer, int length)
{
s32 ret;
ret = 0;
while (length > 0)
{
ERRCK(osEepromRead(mq, address, buffer));
length -= EEPROM_BLOCK_SIZE;
address++;
buffer += EEPROM_BLOCK_SIZE;
}
return ret;
}

View File

@@ -0,0 +1,18 @@
#include <os_internal.h>
#include "controller.h"
s32 osEepromLongWrite(OSMesgQueue *mq, u8 address, u8 *buffer, int length)
{
s32 ret;
ret = 0;
while (length > 0)
{
ERRCK(osEepromWrite(mq, address, buffer));
length -= EEPROM_BLOCK_SIZE;
address++;
buffer += EEPROM_BLOCK_SIZE;
osSetTimer(&__osEepromTimer, 12000 * osClockRate / 1000000, 0, &__osEepromTimerQ, &__osEepromTimerMsg);
osRecvMesg(&__osEepromTimerQ, NULL, OS_MESG_BLOCK);
}
return ret;
}

View File

@@ -0,0 +1,106 @@
#include <rcp.h>
#include "controller.h"
#include "siint.h"
static void __osPackEepReadData(u8 address);
extern OSPifRam __osEepPifRam; // todo bss
s32 osEepromRead(OSMesgQueue *mq, u8 address, u8 *buffer)
{
s32 ret;
int i;
u16 type;
u8 *ptr;
OSContStatus sdata;
__OSContEepromFormat eepromformat;
ret = 0;
i = 0;
ptr = (u8 *)&__osEepPifRam.ramarray;
__osSiGetAccess();
ret = __osEepStatus(mq, &sdata);
type = sdata.type & (CONT_EEPROM | CONT_EEP16K);
if (ret != 0)
{
__osSiRelAccess();
return CONT_NO_RESPONSE_ERROR;
}
switch (type)
{
case CONT_EEPROM:
if (address > EEPROM_MAXBLOCKS)
{
__osSiRelAccess();
return -1;
}
break;
case CONT_EEPROM | CONT_EEP16K:
if (address > EEP16K_MAXBLOCKS) //not technically possible
{
__osSiRelAccess();
return -1;
}
break;
default:
__osSiRelAccess();
return CONT_NO_RESPONSE_ERROR;
break;
}
while (sdata.status & CONT_EEPROM_BUSY)
{
__osEepStatus(mq, &sdata);
}
__osPackEepReadData(address);
ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam); //send command to pif
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++) {
__osEepPifRam.ramarray[i] = 0xFF;
}
__osEepPifRam.pifstatus = 0;
ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); //recv response
__osContLastCmd = CONT_CMD_READ_EEPROM;
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
for (i = 0; i < 4; i++) //skip the first 4 bytes
{
ptr++;
}
eepromformat = *(__OSContEepromFormat *)ptr;
ret = CHNL_ERR(eepromformat);
if (ret == 0)
for (i = 0; i < ARRLEN(eepromformat.data); i++)
*buffer++ = eepromformat.data[i];
__osSiRelAccess();
return ret;
}
static void __osPackEepReadData(u8 address)
{
u8 *ptr;
__OSContEepromFormat eepromformat;
int i;
ptr = (u8 *)&__osEepPifRam.ramarray;
for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++)
{
__osEepPifRam.ramarray[i] = CONT_CMD_NOP;
}
__osEepPifRam.pifstatus = CONT_CMD_EXE;
eepromformat.txsize = CONT_CMD_READ_EEPROM_TX;
eepromformat.rxsize = CONT_CMD_READ_EEPROM_RX;
eepromformat.cmd = CONT_CMD_READ_EEPROM;
eepromformat.address = address;
for (i = 0; i < ARRLEN(eepromformat.data); i++)
{
eepromformat.data[i] = 0;
}
for (i = 0; i < 4; i++) //skip the first 4 bytes
{
*ptr++ = 0;
}
*(__OSContEepromFormat *)(ptr) = eepromformat;
ptr += sizeof(__OSContEepromFormat);
ptr[0] = CONT_CMD_END;
}

View File

@@ -0,0 +1,167 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
#include <rcp.h>
static void __osPackEepWriteData(u8 address, u8 *buffer);
s32 osEepromWrite(OSMesgQueue *mq, u8 address, u8 *buffer)
{
s32 ret;
int i;
u16 type;
u8 *ptr;
__OSContEepromFormat eepromformat;
OSContStatus sdata;
ret = 0;
ptr = (u8 *)&__osEepPifRam.ramarray;
__osSiGetAccess();
ret = __osEepStatus(mq, &sdata); //why is this duplicated?
ret = __osEepStatus(mq, &sdata);
type = sdata.type & (CONT_EEPROM | CONT_EEP16K);
if (ret != 0)
{
__osSiRelAccess();
return CONT_NO_RESPONSE_ERROR;
}
switch (type)
{
case CONT_EEPROM:
if (address > EEPROM_MAXBLOCKS)
{
__osSiRelAccess();
return -1;
}
break;
case CONT_EEPROM | CONT_EEP16K:
if (address > EEP16K_MAXBLOCKS) //not technically possible
{
__osSiRelAccess();
return -1;
}
break;
default:
__osSiRelAccess();
return CONT_NO_RESPONSE_ERROR;
break;
}
while (sdata.status & CONT_EEPROM_BUSY)
{
__osEepStatus(mq, &sdata);
}
__osPackEepWriteData(address, buffer);
ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam); //send command to pif
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++) {
__osEepPifRam.ramarray[i] = 0xFF;
}
__osEepPifRam.pifstatus = 0;
ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); //recv response
__osContLastCmd = CONT_CMD_WRITE_EEPROM;
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
for (i = 0; i < 4; i++) //skip the first 4 bytes
{
ptr++;
}
eepromformat = *(__OSContEepromFormat *)ptr;
//probably indicates an error, from PIF
ret = CHNL_ERR(eepromformat); //TODO: remove magic constants
__osSiRelAccess();
return ret;
}
static void __osPackEepWriteData(u8 address, u8 *buffer)
{
u8 *ptr;
__OSContEepromFormat eepromformat;
int i;
ptr = (u8 *)&__osEepPifRam.ramarray;
for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++)
{
__osEepPifRam.ramarray[i] = CONT_CMD_NOP;
}
__osEepPifRam.pifstatus = CONT_CMD_EXE;
eepromformat.txsize = CONT_CMD_WRITE_EEPROM_TX;
eepromformat.rxsize = CONT_CMD_WRITE_EEPROM_RX;
eepromformat.cmd = CONT_CMD_WRITE_EEPROM;
eepromformat.address = address;
for (i = 0; i < ARRLEN(eepromformat.data); i++)
{
eepromformat.data[i] = *buffer++;
}
for (i = 0; i < 4; i++) //skip the first 4 bytes
{
*ptr++ = 0;
}
*(__OSContEepromFormat *)(ptr) = eepromformat;
ptr += sizeof(__OSContEepromFormat);
ptr[0] = CONT_CMD_END;
}
s32 __osEepStatus(OSMesgQueue *mq, OSContStatus *data)
{
s32 ret;
int i;
u8 *ptr;
__OSContRequesFormat requestformat;
//addiu sp,sp,-48
//lui t6,__osEepPifRam
//addiu t6,t6,__osEepPifRam
//sw ra,20(sp)
//sw a0,48(sp)
//sw a1,52(sp)
//sw zero,44(sp)
ret = 0;
//sw t6,36(sp)
ptr = (u8 *)__osEepPifRam.ramarray;
//could be bset or bzero intrinsic
for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++) //still has the buffer overflow =/, just sets status to 0
{
__osEepPifRam.ramarray[i] = 0;
}
__osEepPifRam.pifstatus = CONT_CMD_EXE;
ptr = (u8 *)__osEepPifRam.ramarray;
for (i = 0; i < 4; i++) //zero 4 bytes?
*ptr++ = 0;
requestformat.dummy = CONT_CMD_NOP;
requestformat.txsize = CONT_CMD_REQUEST_STATUS_TX;
requestformat.rxsize = CONT_CMD_REQUEST_STATUS_RX;
requestformat.cmd = CONT_CMD_REQUEST_STATUS;
requestformat.typeh = CONT_CMD_NOP;
requestformat.typel = CONT_CMD_NOP;
requestformat.status = CONT_CMD_NOP;
requestformat.dummy1 = CONT_CMD_NOP;
*(__OSContRequesFormat *)ptr = requestformat;
ptr += sizeof(__OSContRequesFormat);
*ptr = CONT_CMD_END;
ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
__osContLastCmd = CONT_CMD_REQUEST_STATUS;
ret = __osSiRawStartDma(OS_READ, &__osEepPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
if (ret != 0)
return ret;
ptr = (u8 *)&__osEepPifRam;
for (i = 0; i < 4; i++)
*ptr++ = 0;
requestformat = *(__OSContRequesFormat *)ptr;
data->errno = CHNL_ERR(requestformat);
data->type = (requestformat.typel << 8) | requestformat.typeh;
data->status = requestformat.status;
if (data->errno != 0)
return data->errno;
return 0;
}

302
src/core1/done/io/contpfs.c Normal file
View File

@@ -0,0 +1,302 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "controller.h"
u16 __osSumcalc(u8 *ptr, int length)
{
int i;
u32 sum;
u8 *tmp;
sum = 0;
tmp = ptr;
for (i = 0; i < length; i++)
{
sum += *tmp++;
sum &= 0xffff;
}
return sum;
}
s32 __osIdCheckSum(u16 *ptr, u16 *csum, u16 *icsum)
{
u16 data;
u32 j;
data = 0;
*icsum = 0;
*csum = *icsum;
for (j = 0; j < 28; j += 2)
{
//feels like this should be a compiler optimization not manual..
//but it doesn't match and I'm pretty sure this is just -O1
data = *(u16 *)((u8 *)ptr + j);
//data = ptr[j]
*csum += data;
*icsum += ~data;
}
return 0;
}
s32 __osRepairPackId(OSPfs *pfs, __OSPackId *badid, __OSPackId *newid)
{
s32 ret;
u8 temp[32];
u8 comp[32];
u8 mask;
int i;
int j;
u16 index[4];
ret = 0;
mask = 0;
SET_ACTIVEBANK_TO_ZERO;
newid->repaired = -1;
newid->random = osGetCount();
newid->serial_mid = badid->serial_mid;
newid->serial_low = badid->serial_low;
for (j = 0; j < PFS_MAX_BANKS;)
{
pfs->activebank = j;
ERRCK(__osPfsSelectBank(pfs))
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)&temp)); //TODO: fix magic number
temp[0] = j | 0x80;
for (i = 1; i < ARRLEN(temp); i++)
{
temp[i] = ~temp[i];
}
ERRCK(__osContRamWrite(pfs->queue, pfs->channel, 0, (u8*)temp, FALSE)); //oddr 0, don't force
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)&comp));
for (i = 0; i < ARRLEN(temp); i++)
{
if (comp[i] != temp[i])
break;
}
if (i != ARRLEN(temp))
break;
if (j > 0)
{
pfs->activebank = 0;
ERRCK(__osPfsSelectBank(pfs));
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)temp));
if (temp[0] != 128)
break; //TODO: remove magic constant
}
j++;
}
pfs->activebank = 0;
ERRCK(__osPfsSelectBank(pfs));
if (j > 0)
mask = 1;
else
mask = 0;
newid->deviceid = (badid->deviceid & (u16)~1) | mask;
newid->banks = j;
newid->version = badid->version;
__osIdCheckSum((u16*)newid, &newid->checksum, &newid->inverted_checksum);
index[0] = 1;
index[1] = 3;
index[2] = 4;
index[3] = 6;
for (i = 0; i < ARRLEN(index); i++)
{
ERRCK(__osContRamWrite(pfs->queue, pfs->channel, index[i], (u8*)newid, TRUE));
}
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp));
for (i = 0; i < ARRLEN(temp); i++)
{
if (temp[i] != ((u8 *)newid)[i])
return PFS_ERR_ID_FATAL;
}
return 0;
}
s32 __osCheckPackId(OSPfs *pfs, __OSPackId *temp)
{
u16 index[4];
s32 ret;
u16 sum;
u16 isum;
int i;
int j;
ret = 0;
SET_ACTIVEBANK_TO_ZERO;
index[0] = 1;
index[1] = 3;
index[2] = 4;
index[3] = 6;
for (i = 1; i < ARRLEN(index); i++)
{
ERRCK(__osContRamRead(pfs->queue, pfs->channel, index[i], (u8*)temp));
__osIdCheckSum((u16 *)temp, &sum, &isum);
if (temp->checksum == sum && temp->inverted_checksum == isum)
break;
}
if (i == ARRLEN(index))
return PFS_ERR_ID_FATAL;
for (j = 0; j < ARRLEN(index); j++)
{
if (j != i)
{
ERRCK(__osContRamWrite(pfs->queue, pfs->channel, index[j], (u8*)temp, TRUE));
}
}
return 0;
}
s32 __osGetId(OSPfs *pfs)
{
int k;
u16 sum;
u16 isum;
u8 temp[32];
__OSPackId newid;
s32 ret;
__OSPackId *id;
SET_ACTIVEBANK_TO_ZERO;
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp));
__osIdCheckSum((u16*)temp, &sum, &isum);
id = (__OSPackId*)temp;
if (id->checksum != sum || id->inverted_checksum != isum)
{
ret = __osCheckPackId(pfs, id);
if (ret == PFS_ERR_ID_FATAL)
{
ERRCK(__osRepairPackId(pfs, id, &newid));
id = &newid;
}
else if (ret != 0)
{
return ret;
}
}
if ((id->deviceid & 1) == 0) //TODO: remove magic constant
{
ERRCK(__osRepairPackId(pfs, id, &newid));
id = &newid;
if ((id->deviceid & 1) == 0)
return PFS_ERR_DEVICE;
}
for (k = 0; k < ARRLEN(pfs->id); k++)
{
pfs->id[k] = ((u8 *)id)[k];
}
pfs->version = id->version;
pfs->banks = id->banks;
pfs->inode_start_page = pfs->banks * 2 + 3; //TODO: loads of magic constants..
pfs->dir_size = 16;
pfs->inode_table = 8;
pfs->minode_table = pfs->banks * PFS_ONE_PAGE + 8;
pfs->dir_table = pfs->minode_table + pfs->banks * PFS_ONE_PAGE;
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 7, pfs->label));
return 0;
}
s32 __osCheckId(OSPfs *pfs)
{
int k;
u8 temp[32];
s32 ret;
SET_ACTIVEBANK_TO_ZERO;
ret = __osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp);
if (ret != 0)
{
if (ret != 2)
return ret;
else
ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp));
}
for (k = 0; k < ARRLEN(temp); k++)
{
if (pfs->id[k] != temp[k])
return PFS_ERR_NEW_PACK;
}
return 0;
}
s32 __osPfsRWInode(OSPfs *pfs, __OSInode *inode, u8 flag, u8 bank)
{
u8 sum;
int j;
s32 ret;
int offset;
u8 *addr;
SET_ACTIVEBANK_TO_ZERO;
if (bank > 0)
offset = 1;
else
offset = pfs->inode_start_page;
if (flag == PFS_WRITE)
inode->inode_page[0].inode_t.page = __osSumcalc((u8*)&inode->inode_page[offset], (-offset) * 2 + 256);
for (j = 0; j < 8; j++)
{
addr = ((u8 *)inode->inode_page + j * 32); //TODO: don't like this =/ //maybe &inode->inode_table[j*PFS_ONE_PAGE].ipage or something
if (flag == PFS_WRITE)
{
ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * 8 + j, addr, FALSE);
ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + bank * 8 + j, addr, FALSE);
}
else
{
ret = __osContRamRead(pfs->queue, pfs->channel, pfs->inode_table + bank * 8 + j, addr);
}
if (ret != 0)
return ret;
}
if (flag == PFS_READ)
{
sum = __osSumcalc((u8*)&inode->inode_page[offset], (-offset) * 2 + 256);
if (sum != inode->inode_page[0].inode_t.page)
{
for (j = 0; j < PFS_ONE_PAGE; j++)
{
addr = ((u8 *)inode->inode_page + j * 32);
ret = __osContRamRead(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + j, addr);
}
if (sum != inode->inode_page[0].inode_t.page)
return PFS_ERR_INCONSISTENT;
for (j = 0; j < PFS_ONE_PAGE; j++)
{
addr = ((u8 *)inode->inode_page + j * 32);
ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * PFS_ONE_PAGE + j, addr, FALSE);
}
}
else
{
for (j = 0; j < PFS_ONE_PAGE; j++)
{
addr = ((u8 *)inode->inode_page + j * 32);
ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + j, addr, FALSE);
}
}
}
return 0;
}
s32 __osPfsSelectBank(OSPfs *pfs)
{
u8 temp[BLOCKSIZE];
int i;
s32 ret;
ret = 0;
for (i = 0; i < ARRLEN(temp); i++)
{
temp[i] = pfs->activebank;
}
ret = __osContRamWrite(pfs->queue, pfs->channel, 1024, (u8*)temp, FALSE);
return ret;
}

View File

@@ -0,0 +1,102 @@
#include <os_internal.h>
#include <rcp.h>
#include "controller.h"
#include "siint.h"
static void __osPackRamReadData(int channel, u16 address);
s32 __osContRamRead(OSMesgQueue *mq, int channel, u16 address, u8 *buffer)
{
s32 ret;
int i;
u8 *ptr;
__OSContRamReadFormat ramreadformat;
int retry;
ret = 0;
ptr = (u8 *)&__osPfsPifRam;
retry = 2;
__osSiGetAccess();
__osContLastCmd = CONT_CMD_READ_MEMPACK;
__osPackRamReadData(channel, address);
ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
do
{
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
ptr = (u8 *)&__osPfsPifRam;
if (channel != 0)
{
for (i = 0; i < channel; i++)
{
ptr++;
}
}
ramreadformat = *(__OSContRamReadFormat *)ptr;
ret = CHNL_ERR(ramreadformat);
if (ret == 0)
{
u8 c;
c = __osContDataCrc((u8*)&ramreadformat.data);
if (c != ramreadformat.datacrc)
{
ret = __osPfsGetStatus(mq, channel);
if (ret != 0)
{
__osSiRelAccess();
return ret;
}
ret = PFS_ERR_CONTRFAIL;
}
else
{
for (i = 0; i < ARRLEN(ramreadformat.data); i++)
{
*buffer++ = ramreadformat.data[i];
}
}
}
else
{
ret = PFS_ERR_NOPACK;
}
if (ret != PFS_ERR_CONTRFAIL)
break;
} while (retry-- >= 0);
__osSiRelAccess();
return ret;
}
static void __osPackRamReadData(int channel, u16 address)
{
u8 *ptr;
__OSContRamReadFormat ramreadformat;
int i;
ptr = (u8 *)__osPfsPifRam.ramarray;
for (i = 0; i < ARRLEN(__osPfsPifRam.ramarray) + 1; i++) { // also clear pifstatus
__osPfsPifRam.ramarray[i] = 0;
}
__osPfsPifRam.pifstatus = CONT_CMD_EXE;
ramreadformat.dummy = CONT_CMD_NOP;
ramreadformat.txsize = CONT_CMD_READ_MEMPACK_TX;
ramreadformat.rxsize = CONT_CMD_READ_MEMPACK_RX;
ramreadformat.cmd = CONT_CMD_READ_MEMPACK;
ramreadformat.address = (address << 0x5) | __osContAddressCrc(address);
ramreadformat.datacrc = CONT_CMD_NOP;
for (i = 0; i < ARRLEN(ramreadformat.data); i++)
{
ramreadformat.data[i] = CONT_CMD_NOP;
}
if (channel != 0)
{
for (i = 0; i < channel; i++)
{
*ptr++ = 0;
}
}
*(__OSContRamReadFormat *)ptr = ramreadformat;
ptr += sizeof(__OSContRamReadFormat);
ptr[0] = CONT_CMD_END;
}

View File

@@ -0,0 +1,94 @@
#include <os_internal.h>
#include <rcp.h>
#include "controller.h"
#include "siint.h"
static void __osPackRamWriteData(int channel, u16 address, u8 *buffer);
s32 __osContRamWrite(OSMesgQueue *mq, int channel, u16 address, u8 *buffer, int force)
{
s32 ret;
int i;
u8 *ptr;
__OSContRamReadFormat ramreadformat;
int retry;
ret = 0;
ptr = (u8 *)&__osPfsPifRam;
retry = 2;
if (force != 1 && address < 7 && address != 0)
return 0;
__osSiGetAccess();
__osContLastCmd = CONT_CMD_WRITE_MEMPACK;
__osPackRamWriteData(channel, address, buffer);
ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
do
{
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
ptr = (u8 *)&__osPfsPifRam;
if (channel != 0)
for (i = 0; i < channel; i++)
ptr++;
ramreadformat = *(__OSContRamReadFormat *)ptr;
ret = CHNL_ERR(ramreadformat);
if (ret == 0)
{
if (__osContDataCrc(buffer) != ramreadformat.datacrc)
{
ret = __osPfsGetStatus(mq, channel);
if (ret != 0)
{
__osSiRelAccess();
return ret;
}
ret = PFS_ERR_CONTRFAIL;
}
}
else
{
ret = PFS_ERR_NOPACK;
}
if (ret != PFS_ERR_CONTRFAIL)
break;
} while ((retry-- >= 0));
__osSiRelAccess();
return ret;
}
static void __osPackRamWriteData(int channel, u16 address, u8 *buffer)
{
u8 *ptr;
__OSContRamReadFormat ramreadformat;
int i;
ptr = (u8 *)__osPfsPifRam.ramarray;
for (i = 0; i < ARRLEN(__osPfsPifRam.ramarray) + 1; i++) { // also clear pifstatus
__osPfsPifRam.ramarray[i] = 0;
}
__osPfsPifRam.pifstatus = CONT_CMD_EXE;
ramreadformat.dummy = CONT_CMD_NOP;
ramreadformat.txsize = CONT_CMD_WRITE_MEMPACK_TX;
ramreadformat.rxsize = CONT_CMD_WRITE_MEMPACK_RX;
ramreadformat.cmd = CONT_CMD_WRITE_MEMPACK;
ramreadformat.address = (address << 0x5) | __osContAddressCrc(address);
ramreadformat.datacrc = CONT_CMD_NOP;
for (i = 0; i < ARRLEN(ramreadformat.data); i++)
{
ramreadformat.data[i] = *buffer++;
}
if (channel != 0)
{
for (i = 0; i < channel; i++)
{
*ptr++ = 0;
}
}
*(__OSContRamReadFormat *)ptr = ramreadformat;
ptr += sizeof(__OSContRamReadFormat);
ptr[0] = CONT_CMD_END;
}

View File

@@ -0,0 +1,75 @@
#include <os_internal.h>
#include <rcp.h>
#include "siint.h"
#include "controller.h"
static void __osPackReadData(void);
s32 osContStartReadData(OSMesgQueue *mq)
{
s32 ret;
int i;
ret = 0;
__osSiGetAccess();
if (__osContLastCmd != CONT_CMD_READ_BUTTON)
{
__osPackReadData();
ret = __osSiRawStartDma(OS_WRITE, &__osContPifRam);
osRecvMesg(mq, NULL, OS_MESG_BLOCK);
}
for (i = 0; i < ARRLEN(__osContPifRam.ramarray) + 1; i++)
{
__osContPifRam.ramarray[i] = 0xFF;
}
__osContPifRam.pifstatus = 0;
ret = __osSiRawStartDma(OS_READ, &__osContPifRam);
__osContLastCmd = CONT_CMD_READ_BUTTON;
__osSiRelAccess();
return ret;
}
void osContGetReadData(OSContPad *data)
{
u8 *ptr;
__OSContReadFormat readformat;
int i;
ptr = (u8 *)&__osContPifRam.ramarray;
for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(__OSContReadFormat), data++)
{
readformat = *(__OSContReadFormat *)ptr;
data->errno = CHNL_ERR(readformat);
if (data->errno == 0)
{
data->button = readformat.button;
data->stick_x = readformat.stick_x;
data->stick_y = readformat.stick_y;
}
}
}
static void __osPackReadData(void)
{
u8 *ptr;
__OSContReadFormat readformat;
int i;
ptr = (u8*)&__osContPifRam.ramarray;
for (i = 0; i < ARRLEN(__osContPifRam.ramarray) + 1; i++)
{
__osContPifRam.ramarray[i] = 0;
}
__osContPifRam.pifstatus = CONT_CMD_EXE;
readformat.dummy = CONT_CMD_NOP;
readformat.txsize = CONT_CMD_READ_BUTTON_TX;
readformat.rxsize = CONT_CMD_READ_BUTTON_RX;
readformat.cmd = CONT_CMD_READ_BUTTON;
readformat.button = -1;
readformat.stick_x = -1;
readformat.stick_y = -1;
for(i=0; i < __osMaxControllers; i++){
*(__OSContReadFormat*)ptr = readformat;
ptr += sizeof(__OSContReadFormat);
}
*ptr = CONT_CMD_END;
}

View File

@@ -0,0 +1,95 @@
#include <os_internal.h>
#include <rcp.h>
#include "controller.h"
#include "siint.h"
#define HALF_A_SECOND OS_USEC_TO_CYCLES(500000)
u32 __osContinitialized = 0;
OSPifRam __osContPifRam;
u8 __osContLastCmd;
u8 __osMaxControllers;
OSTimer __osEepromTimer;
OSMesgQueue __osEepromTimerQ;
OSMesg __osEepromTimerMsg;
s32 osContInit(OSMesgQueue *mq, u8 *bitpattern, OSContStatus *data)
{
OSMesg dummy;
s32 ret;
OSTime t;
OSTimer mytimer;
OSMesgQueue timerMesgQueue;
ret = 0;
if (__osContinitialized)
return ret;
__osContinitialized = TRUE;
t = osGetTime();
if (500000 * osClockRate / 1000000 > t)
{
osCreateMesgQueue(&timerMesgQueue, &dummy, 1);
osSetTimer(&mytimer, 500000 * osClockRate / 1000000 - t, 0, &timerMesgQueue, &dummy);
osRecvMesg(&timerMesgQueue, &dummy, OS_MESG_BLOCK);
}
__osMaxControllers = MAXCONTROLLERS;
__osPackRequestData(CONT_CMD_REQUEST_STATUS);
ret = __osSiRawStartDma(OS_WRITE, &__osContPifRam);
osRecvMesg(mq, &dummy, OS_MESG_BLOCK);
ret = __osSiRawStartDma(OS_READ, &__osContPifRam);
osRecvMesg(mq, &dummy, OS_MESG_BLOCK);
__osContGetInitData(bitpattern, data);
__osContLastCmd = CONT_CMD_REQUEST_STATUS;
__osSiCreateAccessQueue();
osCreateMesgQueue(&__osEepromTimerQ, &__osEepromTimerMsg, 1);
return ret;
}
void __osContGetInitData(u8 *pattern, OSContStatus *data)
{
u8 *ptr;
__OSContRequesFormat requestformat;
int i;
u8 bits;
bits = 0;
ptr = (u8 *)&__osContPifRam;
for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(__OSContRequesFormat), data++)
{
requestformat = *(__OSContRequesFormat *)ptr;
data->errno = CHNL_ERR(requestformat);
if (data->errno == 0)
{
data->type = (requestformat.typel << 8) | requestformat.typeh;
data->status = requestformat.status;
bits |= 1 << i;
}
}
*pattern = bits;
}
void __osPackRequestData(u8 cmd)
{
u8 *ptr;
__OSContRequesFormat requestformat;
int i;
for (i = 0; i < ARRLEN(__osContPifRam.ramarray) + 1; i++)
{
__osContPifRam.ramarray[i] = 0;
}
__osContPifRam.pifstatus = CONT_CMD_EXE;
ptr = (u8 *)&__osContPifRam.ramarray;
requestformat.dummy = CONT_CMD_NOP;
requestformat.txsize = CONT_CMD_REQUEST_STATUS_TX;
requestformat.rxsize = CONT_CMD_REQUEST_STATUS_RX;
requestformat.cmd = cmd;
requestformat.typeh = CONT_CMD_NOP;
requestformat.typel = CONT_CMD_NOP;
requestformat.status = CONT_CMD_NOP;
requestformat.dummy1 = CONT_CMD_NOP;
for (i = 0; i < __osMaxControllers; i++)
{
*(__OSContRequesFormat *)ptr = requestformat;
ptr += sizeof(__OSContRequesFormat);
}
ptr[0] = CONT_CMD_END;
}

207
src/core1/done/io/controller.h Executable file
View File

@@ -0,0 +1,207 @@
#ifndef _CONTROLLER_H
#define _CONTROLLER_H
#include <os_internal.h>
#include <rcp.h>
//should go somewhere else but
#define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0])))
#define CHNL_ERR(format) ((format.rxsize & CHNL_ERR_MASK) >> 4)
typedef struct
{
/* 0x0 */ u32 ramarray[15];
/* 0x3C */ u32 pifstatus;
} OSPifRam;
typedef struct
{
/* 0x0 */ u8 dummy;
/* 0x1 */ u8 txsize;
/* 0x2 */ u8 rxsize;
/* 0x3 */ u8 cmd;
/* 0x4 */ u16 button;
/* 0x6 */ s8 stick_x;
/* 0x7 */ s8 stick_y;
} __OSContReadFormat;
typedef struct
{
/* 0x0 */ u8 dummy;
/* 0x1 */ u8 txsize;
/* 0x2 */ u8 rxsize;
/* 0x3 */ u8 cmd;
/* 0x4 */ u8 typeh;
/* 0x5 */ u8 typel;
/* 0x6 */ u8 status;
/* 0x7 */ u8 dummy1;
} __OSContRequesFormat;
typedef struct
{
/* 0x0 */ u8 txsize;
/* 0x1 */ u8 rxsize;
/* 0x2 */ u8 cmd;
/* 0x3 */ u8 typeh;
/* 0x4 */ u8 typel;
/* 0x5 */ u8 status;
} __OSContRequesFormatShort;
typedef struct
{
/* 0x0 */ u8 dummy;
/* 0x1 */ u8 txsize;
/* 0x2 */ u8 rxsize;
/* 0x3 */ u8 cmd;
/* 0x4 */ u16 address;
/* 0x6 */ u8 data[BLOCKSIZE];
/* 0x26 */ u8 datacrc;
} __OSContRamReadFormat;
typedef union {
/* 0x0 */ struct
{
/* 0x0 */ u8 bank;
/* 0x1 */ u8 page;
} inode_t;
/* 0x0 */ u16 ipage;
} __OSInodeUnit;
typedef struct
{
/* 0x0 */ u32 game_code;
/* 0x4 */ u16 company_code;
/* 0x6 */ __OSInodeUnit start_page;
/* 0x8 */ u8 status;
/* 0x9 */ s8 reserved;
/* 0xA */ u16 data_sum;
/* 0xC */ u8 ext_name[PFS_FILE_EXT_LEN];
/* 0x10 */ u8 game_name[PFS_FILE_NAME_LEN];
} __OSDir;
typedef struct
{
/* 0x0 */ __OSInodeUnit inode_page[128];
} __OSInode;
typedef struct
{
/* 0x0 */ u32 repaired;
/* 0x4 */ u32 random;
/* 0x8 */ u64 serial_mid;
/* 0x10 */ u64 serial_low;
/* 0x18 */ u16 deviceid;
/* 0x1A */ u8 banks;
/* 0x1B */ u8 version;
/* 0x1C */ u16 checksum;
/* 0x1E */ u16 inverted_checksum;
} __OSPackId;
typedef struct
{
/* 0x0 */ u8 txsize;
/* 0x1 */ u8 rxsize;
/* 0x2 */ u8 cmd;
/* 0x3 */ u8 address;
/* 0x4 */ u8 data[EEPROM_BLOCK_SIZE];
} __OSContEepromFormat;
//from: http://en64.shoutwiki.com/wiki/SI_Registers_Detailed#CONT_CMD_Usage
#define CONT_CMD_REQUEST_STATUS 0
#define CONT_CMD_READ_BUTTON 1
#define CONT_CMD_READ_MEMPACK 2
#define CONT_CMD_WRITE_MEMPACK 3
#define CONT_CMD_READ_EEPROM 4
#define CONT_CMD_WRITE_EEPROM 5
#define CONT_CMD_RESET 0xff
#define CONT_CMD_REQUEST_STATUS_TX 1
#define CONT_CMD_READ_BUTTON_TX 1
#define CONT_CMD_READ_MEMPACK_TX 3
#define CONT_CMD_WRITE_MEMPACK_TX 35
#define CONT_CMD_READ_EEPROM_TX 2
#define CONT_CMD_WRITE_EEPROM_TX 10
#define CONT_CMD_RESET_TX 1
#define CONT_CMD_REQUEST_STATUS_RX 3
#define CONT_CMD_READ_BUTTON_RX 4
#define CONT_CMD_READ_MEMPACK_RX 33
#define CONT_CMD_WRITE_MEMPACK_RX 1
#define CONT_CMD_READ_EEPROM_RX 8
#define CONT_CMD_WRITE_EEPROM_RX 1
#define CONT_CMD_RESET_RX 3
#define CONT_CMD_NOP 0xff
#define CONT_CMD_END 0xfe //indicates end of a command
#define CONT_CMD_EXE 1 //set pif ram status byte to this to do a command
#define DIR_STATUS_EMPTY 0
#define DIR_STATUS_UNKNOWN 1
#define DIR_STATUS_OCCUPIED 2
typedef struct
{
/* 0x0 */ __OSInode inode;
/* 0x100 */ u8 bank;
/* 0x101 */ u8 map[256];
} __OSInodeCache;
extern s32 __osEepStatus(OSMesgQueue *, OSContStatus *);
u16 __osSumcalc(u8 *ptr, int length);
s32 __osIdCheckSum(u16 *ptr, u16 *csum, u16 *icsum);
s32 __osRepairPackId(OSPfs *pfs, __OSPackId *badid, __OSPackId *newid);
s32 __osCheckPackId(OSPfs *pfs, __OSPackId *temp);
s32 __osGetId(OSPfs *pfs);
s32 __osCheckId(OSPfs *pfs);
s32 __osPfsRWInode(OSPfs *pfs, __OSInode *inode, u8 flag, u8 bank);
s32 __osPfsSelectBank(OSPfs *pfs);
s32 __osPfsDeclearPage(OSPfs *pfs, __OSInode *inode, int file_size_in_pages, int *first_page, u8 bank, int *decleared, int *last_page);
s32 __osPfsReleasePages(OSPfs *pfs, __OSInode *inode, u8 start_page, u16 *sum, u8 bank, __OSInodeUnit *last_page, int flag);
s32 __osBlockSum(OSPfs *pfs, u8 page_no, u16 *sum, u8 bank);
s32 __osContRamRead(OSMesgQueue *mq, int channel, u16 address, u8 *buffer);
s32 __osContRamWrite(OSMesgQueue *mq, int channel, u16 address, u8 *buffer, int force);
void __osContGetInitData(u8 *pattern, OSContStatus *data);
void __osPackRequestData(u8 cmd);
void __osPfsRequestData(u8 cmd);
void __osPfsGetInitData(u8* pattern, OSContStatus* data);
u8 __osContAddressCrc(u16 addr);
u8 __osContDataCrc(u8 *data);
s32 __osPfsGetStatus(OSMesgQueue *queue, int channel);
extern u8 __osContLastCmd;
extern OSTimer __osEepromTimer;
extern OSMesg __osEepromTimerMsg;
extern OSMesgQueue __osEepromTimerQ;
extern OSPifRam __osEepPifRam;
extern OSPifRam __osContPifRam;
extern OSPifRam __osPfsPifRam;
extern u8 __osMaxControllers;
//some version of this almost certainly existed since there's plenty of times where it's used right before a return 0
#define ERRCK(fn) \
ret = fn; \
if (ret != 0) \
return ret;
#define SET_ACTIVEBANK_TO_ZERO \
if (pfs->activebank != 0) \
{ \
pfs->activebank = 0; \
ERRCK(__osPfsSelectBank(pfs)) \
}
#define PFS_CHECK_ID \
if (__osCheckId(pfs) == PFS_ERR_NEW_PACK) \
return PFS_ERR_NEW_PACK;
#endif
#define PFS_CHECK_STATUS \
if ((pfs->status & PFS_INITIALIZED) == 0) \
return PFS_ERR_INVALID;
#define PFS_GET_STATUS \
__osSiGetAccess(); \
ret = __osPfsGetStatus(queue, channel); \
__osSiRelAccess(); \
if (ret != 0) \
return ret;

View File

@@ -0,0 +1,21 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
s32 osContSetCh(u8 ch)
{
s32 ret;
ret = 0;
__osSiGetAccess();
if (ch > MAXCONTROLLERS)
{
__osMaxControllers = 4;
}
else
{
__osMaxControllers = ch;
}
__osContLastCmd = CONT_CMD_END; //TODO: is this right?
__osSiRelAccess();
return ret;
}

47
src/core1/done/io/crc.c Normal file
View File

@@ -0,0 +1,47 @@
#include <os_internal.h>
u8 __osContAddressCrc(u16 addr)
{
u8 temp;
u8 temp2;
int i;
temp = 0;
for (i = 0; i < 16; i++)
{
if (temp & 0x10)
temp2 = 21;
else
temp2 = 0;
temp <<= 1;
temp |= (u8)((addr & 0x400) ? 1 : 0);
addr <<= 1;
temp ^= temp2;
}
return temp & 0x1f;
}
u8 __osContDataCrc(u8 *data)
{
u8 temp;
u8 temp2;
int i;
int j;
temp = 0;
for (i = 0; i <= 32; i++, data++)
{
for (j = 7; j >= 0; j--)
{
if (temp & 0x80)
temp2 = 133;
else
temp2 = 0;
temp <<= 1;
if (i == 32)
temp &= -1;
else
temp |= ((*data & (1 << j)) ? 1 : 0);
temp ^= temp2;
}
}
return temp;
}

113
src/core1/done/io/devmgr.c Normal file
View File

@@ -0,0 +1,113 @@
#include <ultra64.h>
#include "piint.h"
void __osDevMgrMain(void *args)
{
OSIoMesg *mb;
OSMesg em;
OSMesg dummy;
s32 ret;
OSDevMgr *dm;
s32 messageSend;
messageSend = 0;
mb = NULL;
ret = 0;
dm = (OSDevMgr *)args;
while (TRUE)
{
osRecvMesg(dm->cmdQueue, (OSMesg)&mb, OS_MESG_BLOCK);
if (mb->piHandle != NULL &&
mb->piHandle->type == DEVICE_TYPE_64DD &&
(mb->piHandle->transferInfo.cmdType == LEO_CMD_TYPE_0 ||
mb->piHandle->transferInfo.cmdType == LEO_CMD_TYPE_1))
{
__OSBlockInfo *blockInfo;
__OSTranxInfo *info;
info = &mb->piHandle->transferInfo;
blockInfo = &info->block[info->blockNum];
info->sectorNum = -1;
if (info->transferMode != LEO_SECTOR_MODE)
{
blockInfo->dramAddr = (void *)((u32)blockInfo->dramAddr - blockInfo->sectorSize);
}
if (info->transferMode == LEO_TRACK_MODE && mb->piHandle->transferInfo.cmdType == LEO_CMD_TYPE_0)
messageSend = 1;
else
messageSend = 0;
osRecvMesg(dm->acsQueue, &dummy, OS_MESG_BLOCK);
__osResetGlobalIntMask(OS_IM_PI);
osEPiRawWriteIo(mb->piHandle, LEO_BM_CTL, (info->bmCtlShadow | 0x80000000));
while (TRUE)
{
osRecvMesg(dm->evtQueue, &em, OS_MESG_BLOCK);
info = &mb->piHandle->transferInfo;
blockInfo = &info->block[info->blockNum];
if (blockInfo->errStatus == LEO_ERROR_29)
{
u32 stat;
osEPiRawWriteIo(mb->piHandle, LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_RESET); //TODO: remove magic constants
osEPiRawWriteIo(mb->piHandle, LEO_BM_CTL, info->bmCtlShadow);
osEPiRawReadIo(mb->piHandle, LEO_STATUS, &stat);
if (stat & LEO_STATUS_MECHANIC_INTERRUPT) //TODO: remove magic constants
{
osEPiRawWriteIo(mb->piHandle, LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_CLR_MECHANIC_INTR);
}
blockInfo->errStatus = LEO_ERROR_4;
IO_WRITE(PI_STATUS_REG, PI_CLR_INTR);
__osSetGlobalIntMask(OS_IM_PI | SR_IBIT4);
}
osSendMesg(mb->hdr.retQueue, mb, OS_MESG_NOBLOCK);
if (messageSend != 1)
break;
if (mb->piHandle->transferInfo.block[0].errStatus != LEO_ERROR_GOOD)
break;
messageSend = 0;
}
osSendMesg(dm->acsQueue, NULL, OS_MESG_NOBLOCK);
if (mb->piHandle->transferInfo.blockNum == 1)
osYieldThread();
}
else
{
switch (mb->hdr.type)
{
case OS_MESG_TYPE_DMAREAD:
osRecvMesg(dm->acsQueue, &dummy, OS_MESG_BLOCK);
ret = dm->dma(OS_READ, mb->devAddr, mb->dramAddr, mb->size);
break;
case OS_MESG_TYPE_DMAWRITE:
osRecvMesg(dm->acsQueue, &dummy, OS_MESG_BLOCK);
ret = dm->dma(OS_WRITE, mb->devAddr, mb->dramAddr, mb->size);
break;
case OS_MESG_TYPE_EDMAREAD:
osRecvMesg(dm->acsQueue, &dummy, OS_MESG_BLOCK);
ret = dm->edma(mb->piHandle, OS_READ, mb->devAddr, mb->dramAddr,
mb->size);
break;
case OS_MESG_TYPE_EDMAWRITE:
osRecvMesg(dm->acsQueue, &dummy, OS_MESG_BLOCK);
ret = dm->edma(mb->piHandle, OS_WRITE, mb->devAddr, mb->dramAddr,
mb->size);
break;
case OS_MESG_TYPE_LOOPBACK:
osSendMesg(mb->hdr.retQueue, mb, OS_MESG_NOBLOCK);
ret = -1;
break;
default:
ret = -1;
break;
}
if (ret == 0)
{
osRecvMesg(dm->evtQueue, &em, OS_MESG_BLOCK);
osSendMesg(mb->hdr.retQueue, mb, OS_MESG_NOBLOCK);
osSendMesg(dm->acsQueue, NULL, OS_MESG_NOBLOCK);
}
}
}
}

View File

@@ -0,0 +1,6 @@
#include <os_internal.h>
#include <rcp.h>
u32 osDpGetStatus(){
return IO_READ(DPC_STATUS_REG);
}

View File

@@ -0,0 +1,7 @@
#include <os_internal.h>
#include <rcp.h>
void osDpSetStatus(u32 data)
{
IO_WRITE(DPC_STATUS_REG, data);
}

View File

@@ -0,0 +1,66 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
extern OSPiHandle *__osCurrentHandle[2];
#define OS_RAMROM_STACKSIZE 1024
#ifndef WAIT_ON_IOBUSY
#define WAIT_ON_IOBUSY(stat) \
stat = IO_READ(PI_STATUS_REG); \
while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) \
stat = IO_READ(PI_STATUS_REG);
#endif
#define UPDATE_REG(reg, var) \
if (cHandle->var != pihandle->var) \
IO_WRITE(reg, pihandle->var);
#define EPI_SYNC(pihandle, stat, domain) \
\
WAIT_ON_IOBUSY(stat) \
\
domain = pihandle->domain; \
if (__osCurrentHandle[domain] != pihandle) \
{ \
OSPiHandle *cHandle = __osCurrentHandle[domain]; \
if (domain == PI_DOMAIN1) \
{ \
UPDATE_REG(PI_BSD_DOM1_LAT_REG, latency); \
UPDATE_REG(PI_BSD_DOM1_PGS_REG, pageSize); \
UPDATE_REG(PI_BSD_DOM1_RLS_REG, relDuration); \
UPDATE_REG(PI_BSD_DOM1_PWD_REG, pulse); \
} \
else \
{ \
UPDATE_REG(PI_BSD_DOM2_LAT_REG, latency); \
UPDATE_REG(PI_BSD_DOM2_PGS_REG, pageSize); \
UPDATE_REG(PI_BSD_DOM2_RLS_REG, relDuration); \
UPDATE_REG(PI_BSD_DOM2_PWD_REG, pulse); \
} \
__osCurrentHandle[domain] = pihandle; \
}
s32 osEPiRawStartDma(OSPiHandle *pihandle, s32 direction, u32 devAddr, void *dramAddr, u32 size)
{
u32 stat;
u32 domain;
EPI_SYNC(pihandle, stat, domain);
IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr));
IO_WRITE(PI_CART_ADDR_REG, K1_TO_PHYS(pihandle->baseAddress | devAddr));
switch (direction)
{
case OS_READ:
IO_WRITE(PI_WR_LEN_REG, size - 1);
break;
case OS_WRITE:
IO_WRITE(PI_RD_LEN_REG, size - 1);
break;
default:
return -1;
}
return 0;
}

View File

@@ -0,0 +1,14 @@
#include <os_internal.h>
#include <rcp.h>
#include "piint.h"
s32 osEPiRawReadIo(OSPiHandle *pihandle, u32 devAddr, u32 *data)
{
register u32 stat;
register u32 domain;
WAIT_ON_IOBUSY(stat);
*data = IO_READ(pihandle->baseAddress | devAddr);
return 0;
}

View File

@@ -0,0 +1,13 @@
#include <os_internal.h>
#include "piint.h"
s32 osEPiRawWriteIo(OSPiHandle *pihandle, u32 devAddr, u32 data)
{
register u32 stat;
register u32 domain;
WAIT_ON_IOBUSY(stat);
IO_WRITE(pihandle->baseAddress | devAddr, data);
return 0;
}

View File

@@ -0,0 +1,29 @@
#include <os_internal.h>
#include <rcp.h>
#include <os_libc.h>
OSPiHandle LeoDiskHandle;
OSPiHandle *__osDiskHandle;
OSPiHandle *osLeoDiskInit()
{
u32 saveMask;
LeoDiskHandle.type = DEVICE_TYPE_64DD;
LeoDiskHandle.baseAddress = PHYS_TO_K1(PI_DOM2_ADDR1);
LeoDiskHandle.latency = 3;
LeoDiskHandle.pulse = 6;
LeoDiskHandle.pageSize = 6;
LeoDiskHandle.relDuration = 2;
LeoDiskHandle.domain = PI_DOMAIN2;
IO_WRITE(PI_BSD_DOM2_LAT_REG, LeoDiskHandle.latency);
IO_WRITE(PI_BSD_DOM2_PWD_REG, LeoDiskHandle.pulse);
IO_WRITE(PI_BSD_DOM2_PGS_REG, LeoDiskHandle.pageSize);
IO_WRITE(PI_BSD_DOM2_RLS_REG, LeoDiskHandle.relDuration);
LeoDiskHandle.speed = 0;
bzero(&LeoDiskHandle.transferInfo, sizeof(__OSTranxInfo));
saveMask = __osDisableInt();
LeoDiskHandle.next = __osPiTable;
__osPiTable = &LeoDiskHandle;
__osDiskHandle = &LeoDiskHandle;
__osRestoreInt(saveMask);
return &LeoDiskHandle;
}

View File

@@ -0,0 +1,215 @@
#include <ultra64.h>
#include "osint.h"
#include "piint.h"
#define WAIT_ON_IOBUSY2(stat) \
stat = IO_READ(PI_STATUS_REG); \
while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) \
stat = IO_READ(PI_STATUS_REG);
static void __osLeoResume(void);
static void __osLeoAbnormalResume(void);
extern OSThread *__osRunQueue;
extern OSIntMask __OSGlobalIntMask;
extern OSPiHandle *__osDiskHandle;
u8 leoDiskStack[OS_PIM_STACKSIZE];
s32 __osLeoInterrupt()
{
u32 stat;
volatile u32 pi_stat;
u32 bm_stat;
__OSTranxInfo *info;
__OSBlockInfo *blockInfo;
stat = 0;
info = &__osDiskHandle->transferInfo;
blockInfo = &info->block[info->blockNum];
pi_stat = IO_READ(PI_STATUS_REG);
if (pi_stat & PI_STATUS_DMA_BUSY)
{
__OSGlobalIntMask = __OSGlobalIntMask & ~SR_IBIT4; //cartridge interrupt
blockInfo->errStatus = LEO_ERROR_29;
__osLeoResume();
return 1;
}
WAIT_ON_IOBUSY(pi_stat);
stat = IO_READ(LEO_STATUS);
if (stat & LEO_STATUS_MECHANIC_INTERRUPT)
{
WAIT_ON_IOBUSY(pi_stat);
IO_WRITE(LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_CLR_MECHANIC_INTR);
blockInfo->errStatus = LEO_ERROR_GOOD;
return 0;
}
if (info->cmdType == LEO_CMD_TYPE_2)
return 1;
if (stat & LEO_STATUS_BUFFER_MANAGER_ERROR)
{
WAIT_ON_IOBUSY(pi_stat);
stat = IO_READ(LEO_STATUS);
blockInfo->errStatus = LEO_ERROR_22;
__osLeoResume();
IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR);
__OSGlobalIntMask |= OS_IM_PI;
return 1;
}
if (info->cmdType == LEO_CMD_TYPE_1)
{
if ((stat & LEO_STATUS_DATA_REQUEST) == 0)
{
if (info->sectorNum + 1 != info->transferMode * 85)
{
blockInfo->errStatus = LEO_ERROR_24;
__osLeoAbnormalResume();
return 1;
}
IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR);
__OSGlobalIntMask |= OS_IM_PI;
blockInfo->errStatus = LEO_ERROR_GOOD;
__osLeoResume();
return 1;
}
blockInfo->dramAddr = (void *)((u32)blockInfo->dramAddr + blockInfo->sectorSize);
info->sectorNum++;
osEPiRawStartDma(__osDiskHandle, OS_WRITE, LEO_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize);
return 1;
}
if (info->cmdType == LEO_CMD_TYPE_0)
{
if (info->transferMode == LEO_SECTOR_MODE)
{
if ((s32)blockInfo->C1ErrNum + 17 < info->sectorNum)
{
blockInfo->errStatus = LEO_ERROR_GOOD;
__osLeoAbnormalResume();
return 1;
}
if ((stat & LEO_STATUS_DATA_REQUEST) == 0)
{
blockInfo->errStatus = LEO_ERROR_23;
__osLeoAbnormalResume();
return 1;
}
}
else
{
blockInfo->dramAddr = (void *)((u32)blockInfo->dramAddr + blockInfo->sectorSize);
}
bm_stat = IO_READ(LEO_BM_STATUS);
if ((bm_stat & LEO_BM_STATUS_C1SINGLE && bm_stat & LEO_BM_STATUS_C1DOUBLE) || bm_stat & LEO_BM_STATUS_MICRO)
{
if (blockInfo->C1ErrNum > 3)
{
if (info->transferMode != LEO_SECTOR_MODE || info->sectorNum > 0x52)
{
blockInfo->errStatus = LEO_ERROR_23;
__osLeoAbnormalResume();
return 1;
}
}
else
{
int errNum = blockInfo->C1ErrNum;
blockInfo->C1ErrSector[errNum] = info->sectorNum + 1;
}
blockInfo->C1ErrNum += 1;
}
if (stat & LEO_STATUS_C2_TRANSFER)
{
if (info->sectorNum + 1 != 88)
{
blockInfo->errStatus = LEO_ERROR_24;
__osLeoAbnormalResume();
}
if (info->transferMode == LEO_TRACK_MODE && info->blockNum == 0)
{
info->blockNum = 1;
info->sectorNum = -1;
info->block[1].dramAddr = (void *)((u32)info->block[1].dramAddr - info->block[1].sectorSize);
blockInfo->errStatus = LEO_ERROR_22;
}
else
{
IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR);
__OSGlobalIntMask |= OS_IM_PI;
info->cmdType = LEO_CMD_TYPE_2;
blockInfo->errStatus = LEO_ERROR_GOOD;
}
osEPiRawStartDma(__osDiskHandle, OS_READ, LEO_C2_BUFF, blockInfo->C2Addr, blockInfo->sectorSize * 4);
return 1;
}
if (info->sectorNum == -1 && info->transferMode == LEO_TRACK_MODE && info->blockNum == 1)
{
__OSBlockInfo *bptr = &info->block[0];
if (bptr->C1ErrNum == 0)
{
if (((u32 *)bptr->C2Addr)[0] | ((u32 *)bptr->C2Addr)[1] | ((u32 *)bptr->C2Addr)[2] | ((u32 *)bptr->C2Addr)[3])
{
bptr->errStatus = LEO_ERROR_24;
__osLeoAbnormalResume();
return 1;
}
}
bptr->errStatus = 0;
__osLeoResume();
}
info->sectorNum++;
if (stat & LEO_STATUS_DATA_REQUEST)
{
if (info->sectorNum > 0x54)
{
blockInfo->errStatus = LEO_ERROR_24;
__osLeoAbnormalResume();
return 1;
}
osEPiRawStartDma(__osDiskHandle, 0, LEO_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize);
blockInfo->errStatus = LEO_ERROR_GOOD;
return 1;
}
if (info->sectorNum <= 0x54)
{
blockInfo->errStatus = LEO_ERROR_24;
__osLeoAbnormalResume();
return 1;
}
return 1;
}
blockInfo->errStatus = LEO_ERROR_4;
__osLeoAbnormalResume();
return 1;
}
static void __osLeoAbnormalResume(void)
{
__OSTranxInfo *info;
u32 pi_stat;
info = &__osDiskHandle->transferInfo;
pi_stat = pi_stat;
WAIT_ON_IOBUSY2(pi_stat);
IO_WRITE(LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_RESET);
WAIT_ON_IOBUSY2(pi_stat);
IO_WRITE(LEO_BM_CTL, info->bmCtlShadow);
__osLeoResume();
IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR);
__OSGlobalIntMask |= OS_IM_PI;
}
static void __osLeoResume(void)
{
__OSEventState *es;
OSMesgQueue *mq;
s32 last;
es = &__osEventStateTab[OS_EVENT_PI];
mq = es->messageQueue;
if (mq == NULL || MQ_IS_FULL(mq))
return;
last = (mq->first + mq->validCount) % mq->msgCount;
mq->msg[last] = es->message;
mq->validCount++;
if (mq->mtqueue->next != NULL)
__osEnqueueThread(&__osRunQueue, __osPopThread(&mq->mtqueue));
}

170
src/core1/done/io/motor.c Normal file
View File

@@ -0,0 +1,170 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
static void _MakeMotorData(int channel, u16 address, u8 *buffer, OSPifRam *mdata);
// u32 __osMotorinitialized[MAXCONTROLLERS] = {0, 0, 0, 0};
OSPifRam _MotorStopData[MAXCONTROLLERS];
OSPifRam _MotorStartData[MAXCONTROLLERS];
u8 _motorstopbuf[32];
u8 _motorstartbuf[32];
s32 osMotorStop(OSPfs *pfs)
{
int i;
s32 ret;
u8 *ptr;
__OSContRamReadFormat ramreadformat;
ptr = (u8 *)&__osPfsPifRam;
// if (!__osMotorinitialized[pfs->channel])
// return PFS_ERR_INVALID;
__osSiGetAccess();
__osContLastCmd = CONT_CMD_WRITE_MEMPACK;
__osSiRawStartDma(OS_WRITE, &_MotorStopData[pfs->channel]);
osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK);
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK);
ptr = (u8 *)&__osPfsPifRam;
if (pfs->channel != 0)
for (i = 0; i < pfs->channel; i++)
ptr++;
ramreadformat = *(__OSContRamReadFormat *)ptr;
ret = CHNL_ERR(ramreadformat);
if (ret == 0 && ramreadformat.datacrc != 0) //!= __osContDataCrc((u8*)&_motorstopbuf))
{
ret = PFS_ERR_CONTRFAIL;
}
__osSiRelAccess();
return ret;
}
s32 osMotorStart(OSPfs *pfs)
{
int i;
s32 ret;
u8 *ptr;
__OSContRamReadFormat ramreadformat;
ptr = (u8 *)&__osPfsPifRam;
// if (!__osMotorinitialized[pfs->channel])
// return PFS_ERR_INVALID;
__osSiGetAccess();
__osContLastCmd = CONT_CMD_WRITE_MEMPACK;
__osSiRawStartDma(OS_WRITE, &_MotorStartData[pfs->channel]);
osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK);
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK);
ptr = (u8 *)&__osPfsPifRam;
if (pfs->channel != 0)
for (i = 0; i < pfs->channel; i++)
ptr++;
ramreadformat = *(__OSContRamReadFormat *)ptr;
ret = CHNL_ERR(ramreadformat);
if (ret == 0 && ramreadformat.datacrc != 0xEB)//__osContDataCrc((u8*)&_motorstartbuf))
{
ret = PFS_ERR_CONTRFAIL;
}
__osSiRelAccess();
return ret;
}
static void _MakeMotorData(int channel, u16 address, u8 *buffer, OSPifRam *mdata)
{
u8 *ptr;
__OSContRamReadFormat ramreadformat;
int i;
ptr = (u8 *)mdata->ramarray;
for (i = 0; i < ARRLEN(mdata->ramarray); i++)
mdata->ramarray[i] = 0;
mdata->pifstatus = CONT_CMD_EXE;
ramreadformat.dummy = CONT_CMD_NOP;
ramreadformat.txsize = CONT_CMD_WRITE_MEMPACK_TX;
ramreadformat.rxsize = CONT_CMD_WRITE_MEMPACK_RX;
ramreadformat.cmd = CONT_CMD_WRITE_MEMPACK;
ramreadformat.address = (address << 0x5) | __osContAddressCrc(address);
ramreadformat.datacrc = CONT_CMD_NOP;
for (i = 0; i < ARRLEN(ramreadformat.data); i++)
ramreadformat.data[i] = *buffer++;
if (channel != 0)
{
for (i = 0; i < channel; i++)
{
*ptr++ = 0;
}
}
*(__OSContRamReadFormat *)ptr = ramreadformat;
ptr += sizeof(__OSContRamReadFormat);
ptr[0] = CONT_CMD_END;
}
s32 osMotorInit(OSMesgQueue *mq, OSPfs *pfs, int channel)
{
int i;
s32 ret;
u8 temp[32];
pfs->queue = mq;
pfs->channel = channel;
pfs->status = 0;
pfs->activebank = 128;
for (i = 0; i < ARRLEN(temp); i++)
temp[i] = 0x80;
ret = __osContRamWrite(mq, channel, 1024, temp, FALSE);
if (ret == 2) //TODO: remove magic constant
ret = __osContRamWrite(mq, channel, 1024, temp, FALSE);
if (ret != 0)
return ret;
ret = __osContRamRead(mq, channel, 1024, temp);
if (ret == 2)
ret = PFS_ERR_CONTRFAIL; //is this right?
if (ret != 0)
return ret;
if (temp[31] != 0x80)
return PFS_ERR_DEVICE;
// for (i = 0; i < ARRLEN(temp); i++)
// temp[i] = 128;
// ret = __osContRamWrite(mq, channel, 1024, temp, FALSE);
// if (ret == 2)
// ret = __osContRamWrite(mq, channel, 1024, temp, FALSE);
// if (ret != 0)
// return ret;
// ret = __osContRamRead(mq, channel, 1024, temp);
// if (ret == 2)
// ret = PFS_ERR_CONTRFAIL;
// if (ret != 0)
// return ret;
// if (temp[31] != 128)
// return PFS_ERR_DEVICE;
// if (!__osMotorinitialized[channel])
// {
for (i = 0; i < ARRLEN(_motorstartbuf); i++)
{
_motorstartbuf[i] = 1;
_motorstopbuf[i] = 0;
}
_MakeMotorData(channel, 1536, _motorstartbuf, &_MotorStartData[channel]);
_MakeMotorData(channel, 1536, _motorstopbuf, &_MotorStopData[channel]);
// __osMotorinitialized[channel] = 1;
// }
return 0;
}

View File

@@ -0,0 +1,207 @@
#include <os_internal.h>
#include "controller.h"
s32 corrupted_init(OSPfs *pfs, __OSInodeCache *cache);
s32 corrupted(OSPfs *pfs, __OSInodeUnit fpage, __OSInodeCache *cache);
s32 osPfsChecker(OSPfs *pfs)
{
int j; //1156
s32 ret; //1152
__OSInodeUnit next_page;
__OSInode checked_inode;
__OSInode tmp_inode; //636
__OSDir tmp_dir;
__OSInodeUnit file_next_node[16];
__OSInodeCache cache; //56
int fixed; //52
u8 bank; //51
s32 cc; //44
s32 cl; //40
int offset; //36
fixed = 0;
ret = __osCheckId(pfs);
if (ret == PFS_ERR_NEW_PACK)
ret = __osGetId(pfs);
if (ret != 0)
return ret;
ERRCK(corrupted_init(pfs, &cache));
for (j = 0; j < pfs->dir_size; j++)
{
ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir));
if (tmp_dir.company_code != 0 && tmp_dir.game_code != 0)
{
next_page = tmp_dir.start_page;
cc = 0;
cl = 0;
bank = 255;
while (next_page.ipage >= pfs->inode_start_page && next_page.inode_t.bank < pfs->banks && next_page.inode_t.page > 0 && next_page.inode_t.page < 128)
{
if (bank != next_page.inode_t.bank)
{
bank = next_page.inode_t.bank;
ret = __osPfsRWInode(pfs, &tmp_inode, OS_READ, bank);
if (ret != 0 && ret != PFS_ERR_INCONSISTENT)
return ret;
}
cc = corrupted(pfs, next_page, &cache) - cl;
if (cc != 0)
break;
cl = 1;
next_page = tmp_inode.inode_page[next_page.inode_t.page];
}
if (cc == 0 && next_page.ipage == 1)
continue;
tmp_dir.company_code = 0;
tmp_dir.game_code = 0;
tmp_dir.start_page.ipage = 0;
tmp_dir.status = DIR_STATUS_EMPTY;
tmp_dir.data_sum = 0;
SET_ACTIVEBANK_TO_ZERO;
ERRCK(__osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir, FALSE));
fixed++;
}
else
{
if (tmp_dir.company_code == 0 && tmp_dir.game_code == 0)
continue;
tmp_dir.company_code = 0;
tmp_dir.game_code = 0;
tmp_dir.start_page.ipage = 0;
tmp_dir.status = DIR_STATUS_EMPTY;
tmp_dir.data_sum = 0;
SET_ACTIVEBANK_TO_ZERO;
ERRCK(__osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir, FALSE));
fixed++;
}
}
for (j = 0; j < pfs->dir_size; j++)
{
ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir));
if (tmp_dir.company_code != 0 && tmp_dir.game_code != 0 &&
tmp_dir.start_page.ipage >= ((__OSInodeUnit *)&(pfs->inode_start_page) + 1)->ipage) //weird
{
file_next_node[j].ipage = tmp_dir.start_page.ipage;
}
else
{
file_next_node[j].ipage = 0;
}
}
for (bank = 0; bank < pfs->banks; bank++)
{
ret = __osPfsRWInode(pfs, &tmp_inode, 0, bank);
if (ret != 0 && ret != PFS_ERR_INCONSISTENT)
return ret;
if (bank > 0)
{
offset = 1;
}
else
{
offset = pfs->inode_start_page;
}
for (j = 0; j < offset; j++)
{
checked_inode.inode_page[j].ipage = tmp_inode.inode_page[j].ipage;
}
for (; j < 128; j++)
{
checked_inode.inode_page[j].ipage = 3;
}
for (j = 0; j < pfs->dir_size; j++)
{
while (file_next_node[j].inode_t.bank == bank && file_next_node[j].ipage >= ((__OSInodeUnit *)&(pfs->inode_start_page) + 1)->ipage)
{
u8 pp = file_next_node[j].inode_t.page;
file_next_node[j] = checked_inode.inode_page[pp] = tmp_inode.inode_page[pp];
}
}
ERRCK(__osPfsRWInode(pfs, &checked_inode, OS_WRITE, bank));
}
if (fixed)
pfs->status |= PFS_CORRUPTED;
else
pfs->status &= ~PFS_CORRUPTED;
return 0;
}
s32 corrupted_init(OSPfs *pfs, __OSInodeCache *cache)
{
int i;
int n;
int offset;
u8 bank;
__OSInodeUnit tpage;
__OSInode tmp_inode;
s32 ret;
for (i = 0; i < ARRLEN(cache->map); i++)
cache->map[i] = 0;
cache->bank = -1;
for (bank = 0; bank < pfs->banks; bank++)
{
if (bank > 0)
offset = 1;
else
offset = pfs->inode_start_page;
ret = __osPfsRWInode(pfs, &tmp_inode, OS_READ, bank);
if (ret != 0 && ret != PFS_ERR_INCONSISTENT)
return ret;
for (i = offset; i < ARRLEN(tmp_inode.inode_page); i++)
{
tpage = tmp_inode.inode_page[i];
if (tpage.ipage >= pfs->inode_start_page && tpage.inode_t.bank != bank)
{
n = (tpage.inode_t.page / 4) + ((tpage.inode_t.bank % PFS_ONE_PAGE) * BLOCKSIZE);
cache->map[n] |= 1 << (bank % PFS_ONE_PAGE);
}
}
}
return 0;
}
s32 corrupted(OSPfs *pfs, __OSInodeUnit fpage, __OSInodeCache *cache)
{
int j;
int n;
int hit;
u8 bank;
int offset;
s32 ret;
hit = 0;
ret = 0;
n = (fpage.inode_t.page / 4) + (fpage.inode_t.bank % 8) * BLOCKSIZE;
for (bank = 0; bank < pfs->banks; bank++)
{
if (bank > 0)
offset = 1;
else
offset = pfs->inode_start_page;
if (bank == fpage.inode_t.bank || cache->map[n] & (1 << (bank % 8)))
{
if (bank != cache->bank)
{
ret = __osPfsRWInode(pfs, &cache->inode, 0, bank);
if (ret != 0 && ret != PFS_ERR_INCONSISTENT)
return ret;
cache->bank = bank;
}
for (j = offset; hit < 2 && (j < ARRLEN(cache->inode.inode_page)); j++)
{
if (cache->inode.inode_page[j].ipage == fpage.ipage)
hit++;
}
if (1 < hit)
return PFS_ERR_NEW_PACK;
}
}
return hit;
}

View File

@@ -0,0 +1,26 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
OSPifRam __osPfsPifRam;
s32 __osPfsGetStatus(OSMesgQueue *queue, int channel)
{
s32 ret;
OSMesg dummy;
u8 pattern;
OSContStatus data[4];
ret = 0;
__osPfsRequestData(CONT_CMD_REQUEST_STATUS);
ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
osRecvMesg(queue, &dummy, OS_MESG_BLOCK);
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(queue, &dummy, OS_MESG_BLOCK);
__osPfsGetInitData(&pattern, data);
if (((data[channel].status & CONT_CARD_ON) != 0) && ((data[channel].status & CONT_CARD_PULL) != 0))
return PFS_ERR_NEW_PACK;
if ((data[channel].errno != 0) || ((data[channel].status & CONT_CARD_ON) == 0))
return PFS_ERR_NOPACK;
if ((data[channel].status & CONT_ADDR_CRC_ER) != 0)
return PFS_ERR_CONTRFAIL;
return ret;
}

View File

@@ -0,0 +1,24 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
s32 osPfsInit(OSMesgQueue *queue, OSPfs *pfs, int channel)
{
s32 ret;
ret = 0;
__osSiGetAccess();
ret = __osPfsGetStatus(queue, channel);
__osSiRelAccess();
if (ret != 0)
return ret;
pfs->queue = queue;
pfs->channel = channel;
pfs->status = 0;
pfs->activebank = -1;
ERRCK(__osGetId(pfs));
ret = osPfsChecker(pfs);
pfs->status |= PFS_INITIALIZED;
return ret;
}

View File

@@ -0,0 +1,99 @@
#include <os_internal.h>
#include "controller.h"
#include "siint.h"
extern OSPifRam __osPfsPifRam; // TODO bss
s32 osPfsIsPlug(OSMesgQueue *queue, u8 *pattern)
{
s32 ret;
OSMesg dummy;
u8 bitpattern;
OSContStatus data[MAXCONTROLLERS];
int channel;
u8 bits;
int crc_error_cnt;
ret = 0;
bits = 0;
crc_error_cnt = 3;
__osSiGetAccess();
while (TRUE)
{
__osPfsRequestData(CONT_CMD_REQUEST_STATUS);
ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
osRecvMesg(queue, &dummy, OS_MESG_BLOCK);
ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
osRecvMesg(queue, &dummy, OS_MESG_BLOCK);
__osPfsGetInitData(&bitpattern, data);
for (channel = 0; channel < __osMaxControllers; channel++)
{
if ((data[channel].status & CONT_ADDR_CRC_ER) == 0)
{
crc_error_cnt--;
break;
}
}
if (__osMaxControllers == channel)
crc_error_cnt = 0;
if (crc_error_cnt < 1)
{
for (channel = 0; channel < __osMaxControllers; channel++)
{
if (data[channel].errno == 0 && (data[channel].status & CONT_CARD_ON) != 0)
bits |= 1 << channel;
}
__osSiRelAccess();
*pattern = bits;
return ret;
}
}
}
void __osPfsRequestData(u8 cmd)
{
u8 *ptr;
__OSContRequesFormat requestformat;
int i;
__osContLastCmd = cmd;
for (i = 0; i < ARRLEN(__osPfsPifRam.ramarray) + 1; i++) { // also clear pifstatus
__osPfsPifRam.ramarray[i] = 0;
}
__osPfsPifRam.pifstatus = CONT_CMD_EXE;
ptr = (u8 *)&__osPfsPifRam;
requestformat.dummy = CONT_CMD_NOP;
requestformat.txsize = CONT_CMD_REQUEST_STATUS_TX;
requestformat.rxsize = CONT_CMD_REQUEST_STATUS_RX;
requestformat.cmd = cmd;
requestformat.typeh = CONT_CMD_NOP;
requestformat.typel = CONT_CMD_NOP;
requestformat.status = CONT_CMD_NOP;
requestformat.dummy1 = CONT_CMD_NOP;
for (i = 0; i < __osMaxControllers; i++)
{
*(__OSContRequesFormat *)ptr = requestformat;
ptr += sizeof(__OSContRequesFormat);
}
*ptr = CONT_CMD_END;
}
void __osPfsGetInitData(u8 *pattern, OSContStatus *data)
{
u8 *ptr;
__OSContRequesFormat requestformat;
int i;
u8 bits;
bits = 0;
ptr = (u8 *)&__osPfsPifRam;
for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(__OSContRequesFormat))
{
requestformat = *(__OSContRequesFormat *)ptr;
data->errno = CHNL_ERR(requestformat);
if (data->errno == 0)
{
data->type = (requestformat.typel << 8) | (requestformat.typeh);
data->status = requestformat.status;
bits |= 1 << i;
}
data++;
}
*pattern = bits;
}

24
src/core1/done/io/piacs.c Normal file
View File

@@ -0,0 +1,24 @@
#include <os_internal.h>
#define PI_Q_BUF_LEN 1
u32 __osPiAccessQueueEnabled = 0;
extern OSMesg piAccessBuf[PI_Q_BUF_LEN]; // todo bss
extern OSMesgQueue __osPiAccessQueue;
void __osPiCreateAccessQueue(void)
{
__osPiAccessQueueEnabled = 1;
osCreateMesgQueue(&__osPiAccessQueue, piAccessBuf, PI_Q_BUF_LEN);
osSendMesg(&__osPiAccessQueue, NULL, OS_MESG_NOBLOCK);
}
void __osPiGetAccess(void)
{
OSMesg dummyMesg;
if (!__osPiAccessQueueEnabled)
__osPiCreateAccessQueue();
osRecvMesg(&__osPiAccessQueue, &dummyMesg, OS_MESG_BLOCK);
}
void __osPiRelAccess(void)
{
osSendMesg(&__osPiAccessQueue, NULL, OS_MESG_NOBLOCK);
}

View File

@@ -0,0 +1,11 @@
#include <ultra64.h>
#include "functions.h"
#include "variables.h"
extern OSDevMgr __osPiDevMgr;
OSMesgQueue *osPiGetCmdQueue(void){
if (!__osPiDevMgr.active)
return NULL;
return __osPiDevMgr.cmdQueue;
}

50
src/core1/done/io/pimgr.c Normal file
View File

@@ -0,0 +1,50 @@
#include <ultra64.h>
#include "piint.h"
extern u32 __osPiAccessQueueEnabled;
OSDevMgr __osPiDevMgr = {0};
OSPiHandle *__osPiTable = NULL;
OSPiHandle *__osCurrentHandle[2] = {&CartRomHandle, &LeoDiskHandle};
extern OSThread piThread;
extern char piThreadStack[OS_PIM_STACKSIZE];
extern OSMesgQueue piEventQueue;
extern OSMesg piEventBuf;
void osCreatePiManager(OSPri pri, OSMesgQueue *cmdQ, OSMesg *cmdBuf, s32 cmdMsgCnt)
{
u32 savedMask;
OSPri oldPri;
OSPri myPri;
if (!__osPiDevMgr.active)
{
osCreateMesgQueue(cmdQ, cmdBuf, cmdMsgCnt);
osCreateMesgQueue(&piEventQueue, (OSMesg*)&piEventBuf, 1);
if (!__osPiAccessQueueEnabled)
__osPiCreateAccessQueue();
osSetEventMesg(OS_EVENT_PI, &piEventQueue, (OSMesg)0x22222222);
oldPri = -1;
myPri = osGetThreadPri(NULL);
if (myPri < pri)
{
oldPri = myPri;
osSetThreadPri(NULL, pri);
}
savedMask = __osDisableInt();
__osPiDevMgr.active = 1;
__osPiDevMgr.thread = &piThread;
__osPiDevMgr.cmdQueue = cmdQ;
__osPiDevMgr.evtQueue = &piEventQueue;
__osPiDevMgr.acsQueue = &__osPiAccessQueue;
__osPiDevMgr.dma = osPiRawStartDma;
__osPiDevMgr.edma = osEPiRawStartDma;
osCreateThread(&piThread, 0, __osDevMgrMain, &__osPiDevMgr, &piThreadStack[OS_PIM_STACKSIZE], pri);
osStartThread(&piThread);
__osRestoreInt(savedMask);
if (oldPri != -1)
{
osSetThreadPri(NULL, oldPri);
}
}
}

View File

@@ -0,0 +1,28 @@
#include <ultra64.h>
#ifndef WAIT_ON_IOBUSY
#define WAIT_ON_IOBUSY(stat) \
stat = IO_READ(PI_STATUS_REG); \
while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) \
stat = IO_READ(PI_STATUS_REG);
#endif
s32 osPiRawStartDma(s32 direction, u32 devAddr, void *dramAddr, u32 size)
{
register u32 stat;
WAIT_ON_IOBUSY(stat);
IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr));
IO_WRITE(PI_CART_ADDR_REG, K1_TO_PHYS((u32)osRomBase | devAddr));
switch (direction)
{
case OS_READ:
IO_WRITE(PI_WR_LEN_REG, size - 1);
break;
case OS_WRITE:
IO_WRITE(PI_RD_LEN_REG, size - 1);
break;
default:
return -1;
}
return 0;
}

View File

@@ -0,0 +1,11 @@
#include <ultra64.h>
#include "piint.h"
s32 osPiRawReadIo(u32 devAddr, u32 *data)
{
register u32 stat;
WAIT_ON_IOBUSY(stat);
*data = IO_READ((u32)osRomBase | devAddr);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More