The first commit
This commit is contained in:
42
src/core1/done/audio/auxbus.c
Normal file
42
src/core1/done/audio/auxbus.c
Normal 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
118
src/core1/done/audio/bnkf.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
23
src/core1/done/audio/cents2ratio.c
Normal file
23
src/core1/done/audio/cents2ratio.c
Normal 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;
|
||||
}
|
14
src/core1/done/audio/code_219D0.c
Normal file
14
src/core1/done/audio/code_219D0.c
Normal 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);
|
||||
}
|
9
src/core1/done/audio/code_21A80.c
Normal file
9
src/core1/done/audio/code_21A80.c
Normal 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;
|
||||
}
|
16
src/core1/done/audio/code_21AF0.c
Normal file
16
src/core1/done/audio/code_21AF0.c
Normal 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);
|
||||
}
|
40
src/core1/done/audio/code_21B50.c
Normal file
40
src/core1/done/audio/code_21B50.c
Normal 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);
|
||||
}
|
14
src/core1/done/audio/copy.c
Normal file
14
src/core1/done/audio/copy.c
Normal 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
375
src/core1/done/audio/cseq.c
Normal 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);
|
||||
}
|
10
src/core1/done/audio/cspgettempo.c
Normal file
10
src/core1/done/audio/cspgettempo.c
Normal 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;
|
||||
}
|
||||
|
12
src/core1/done/audio/cspplay.c
Normal file
12
src/core1/done/audio/cspplay.c
Normal 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);
|
||||
}
|
13
src/core1/done/audio/cspsetbank.c
Normal file
13
src/core1/done/audio/cspsetbank.c
Normal 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);
|
||||
}
|
11
src/core1/done/audio/cspsetseq.c
Normal file
11
src/core1/done/audio/cspsetseq.c
Normal 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);
|
||||
}
|
17
src/core1/done/audio/cspsettempo.c
Normal file
17
src/core1/done/audio/cspsettempo.c
Normal 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);
|
||||
}
|
15
src/core1/done/audio/cspsetvol.c
Normal file
15
src/core1/done/audio/cspsetvol.c
Normal 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);
|
||||
}
|
||||
|
10
src/core1/done/audio/cspstop.c
Normal file
10
src/core1/done/audio/cspstop.c
Normal 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);
|
||||
}
|
280
src/core1/done/audio/drvrNew.c
Normal file
280
src/core1/done/audio/drvrNew.c
Normal 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
495
src/core1/done/audio/env.c
Normal 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;
|
||||
}
|
||||
|
137
src/core1/done/audio/event.c
Normal file
137
src/core1/done/audio/event.c
Normal 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);
|
||||
}
|
||||
|
||||
|
12
src/core1/done/audio/filter.c
Normal file
12
src/core1/done/audio/filter.c
Normal 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;
|
||||
}
|
43
src/core1/done/audio/heapalloc.c
Normal file
43
src/core1/done/audio/heapalloc.c
Normal 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;
|
||||
}
|
16
src/core1/done/audio/heapinit.c
Normal file
16
src/core1/done/audio/heapinit.c
Normal 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
446
src/core1/done/audio/load.c
Normal 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;
|
||||
}
|
46
src/core1/done/audio/mainbus.c
Normal file
46
src/core1/done/audio/mainbus.c
Normal 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;
|
||||
|
||||
}
|
23
src/core1/done/audio/n_auxbus.c
Normal file
23
src/core1/done/audio/n_auxbus.c
Normal 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;
|
||||
}
|
870
src/core1/done/audio/n_csplayer.c
Normal file
870
src/core1/done/audio/n_csplayer.c
Normal 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. */
|
||||
}
|
292
src/core1/done/audio/n_csq.c
Normal file
292
src/core1/done/audio/n_csq.c
Normal 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);
|
||||
}
|
188
src/core1/done/audio/n_drvrNew.c
Normal file
188
src/core1/done/audio/n_drvrNew.c
Normal 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;
|
||||
}
|
||||
|
||||
|
40
src/core1/done/audio/n_envresample.c
Normal file
40
src/core1/done/audio/n_envresample.c
Normal 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;
|
||||
}
|
87
src/core1/done/audio/n_load.c
Normal file
87
src/core1/done/audio/n_load.c
Normal 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;
|
||||
}
|
||||
}
|
28
src/core1/done/audio/n_mainbus.c
Normal file
28
src/core1/done/audio/n_mainbus.c
Normal 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;
|
||||
}
|
||||
|
116
src/core1/done/audio/n_resample.c
Normal file
116
src/core1/done/audio/n_resample.c
Normal 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;
|
||||
}
|
||||
|
2
src/core1/done/audio/n_resample_add01.c_
Normal file
2
src/core1/done/audio/n_resample_add01.c_
Normal file
@@ -0,0 +1,2 @@
|
||||
n_aResample(ptr++, osVirtualToPhysical(e->rs_state), e->rs_first, incr, inp, 0);
|
||||
|
19
src/core1/done/audio/n_save.c
Normal file
19
src/core1/done/audio/n_save.c
Normal 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;
|
||||
}
|
2
src/core1/done/audio/n_save_add01.c_
Normal file
2
src/core1/done/audio/n_save_add01.c_
Normal file
@@ -0,0 +1,2 @@
|
||||
n_aInterleave(ptr++);
|
||||
n_aSaveBuffer(ptr++, FIXED_SAMPLE<<2, 0, n_syn->sv_dramout);
|
68
src/core1/done/audio/n_synaddplayer.c
Normal file
68
src/core1/done/audio/n_synaddplayer.c
Normal 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);
|
||||
}
|
10
src/core1/done/audio/n_synallocfx.c
Normal file
10
src/core1/done/audio/n_synallocfx.c
Normal 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]);
|
||||
}
|
107
src/core1/done/audio/n_synallocvoice.c
Normal file
107
src/core1/done/audio/n_synallocvoice.c
Normal 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;
|
||||
}
|
30
src/core1/done/audio/n_synfreevoice.c
Normal file
30
src/core1/done/audio/n_synfreevoice.c
Normal 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;
|
||||
|
||||
}
|
||||
}
|
29
src/core1/done/audio/n_synsetfxmix.c
Normal file
29
src/core1/done/audio/n_synsetfxmix.c
Normal 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);
|
||||
}
|
||||
}
|
27
src/core1/done/audio/n_synsetpan.c
Normal file
27
src/core1/done/audio/n_synsetpan.c
Normal 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);
|
||||
}
|
||||
}
|
27
src/core1/done/audio/n_synsetpitch.c
Normal file
27
src/core1/done/audio/n_synsetpitch.c
Normal 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);
|
||||
}
|
||||
}
|
30
src/core1/done/audio/n_synsetvol.c
Normal file
30
src/core1/done/audio/n_synsetvol.c
Normal 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);
|
||||
}
|
||||
}
|
49
src/core1/done/audio/n_synstartvoice.c
Normal file
49
src/core1/done/audio/n_synstartvoice.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
42
src/core1/done/audio/n_synstartvoiceparam.c
Normal file
42
src/core1/done/audio/n_synstartvoiceparam.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
20
src/core1/done/audio/n_synstopvoice.c
Normal file
20
src/core1/done/audio/n_synstopvoice.c
Normal 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);
|
||||
}
|
||||
}
|
359
src/core1/done/audio/n_synthesizer.c
Normal file
359
src/core1/done/audio/n_synthesizer.c
Normal 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= ¶ms[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;
|
||||
}
|
125
src/core1/done/audio/resample.c
Normal file
125
src/core1/done/audio/resample.c
Normal 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;
|
||||
}
|
431
src/core1/done/audio/reverb.c
Normal file
431
src/core1/done/audio/reverb.c
Normal 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);
|
||||
}
|
41
src/core1/done/audio/save.c
Normal file
41
src/core1/done/audio/save.c
Normal 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
309
src/core1/done/audio/seq.c
Normal 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
38
src/core1/done/audio/sl.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
12
src/core1/done/audio/synallocfx.c
Normal file
12
src/core1/done/audio/synallocfx.c
Normal 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]);
|
||||
}
|
6
src/core1/done/audio/syndelete.c
Normal file
6
src/core1/done/audio/syndelete.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <ultra64.h>
|
||||
|
||||
void alSynDelete(ALSynth *drvr)
|
||||
{
|
||||
drvr->head = 0;
|
||||
}
|
303
src/core1/done/audio/synthesizer.c
Normal file
303
src/core1/done/audio/synthesizer.c
Normal 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= ¶ms[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;
|
||||
}
|
||||
|
15
src/core1/done/code_1D590.c
Normal file
15
src/core1/done/code_1D590.c
Normal 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
133
src/core1/done/code_1E360.c
Normal 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);
|
||||
}
|
||||
|
36
src/core1/done/code_1E8C0.c
Normal file
36
src/core1/done/code_1E8C0.c
Normal 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
651
src/core1/done/code_CE60.c
Normal 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
42
src/core1/done/gu/guint.h
Normal 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;
|
15
src/core1/done/gu/normalize.c
Normal file
15
src/core1/done/gu/normalize.c
Normal 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
31
src/core1/done/gu/ortho.c
Normal 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
157
src/core1/done/gu/sinf.c
Normal 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 );
|
||||
}
|
||||
|
8
src/core1/done/gu/sqrtf.c
Normal file
8
src/core1/done/gu/sqrtf.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <ultra64.h>
|
||||
#include "functions.h"
|
||||
#include "variables.h"
|
||||
|
||||
|
||||
float gu_sqrtf(float val){
|
||||
return sqrtf(val);
|
||||
}
|
22
src/core1/done/gu/translate.c
Normal file
22
src/core1/done/gu/translate.c
Normal 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
12
src/core1/done/io/ai.c
Normal 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;
|
||||
}
|
6
src/core1/done/io/aigetlen.c
Normal file
6
src/core1/done/io/aigetlen.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <rcp.h>
|
||||
|
||||
u32 osAiGetLength(void)
|
||||
{
|
||||
return IO_READ(AI_LEN_REG);
|
||||
}
|
20
src/core1/done/io/aisetfreq.c
Normal file
20
src/core1/done/io/aisetfreq.c
Normal 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;
|
||||
}
|
23
src/core1/done/io/aisetnextbuf.c
Normal file
23
src/core1/done/io/aisetnextbuf.c
Normal 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;
|
||||
}
|
36
src/core1/done/io/cartrominit.c
Normal file
36
src/core1/done/io/cartrominit.c
Normal 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;
|
||||
}//*/
|
15
src/core1/done/io/conteeplongread.c
Normal file
15
src/core1/done/io/conteeplongread.c
Normal 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;
|
||||
}
|
18
src/core1/done/io/conteeplongwrite.c
Normal file
18
src/core1/done/io/conteeplongwrite.c
Normal 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;
|
||||
}
|
106
src/core1/done/io/conteepread.c
Normal file
106
src/core1/done/io/conteepread.c
Normal 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;
|
||||
}
|
167
src/core1/done/io/conteepwrite.c
Normal file
167
src/core1/done/io/conteepwrite.c
Normal 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
302
src/core1/done/io/contpfs.c
Normal 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;
|
||||
}
|
102
src/core1/done/io/contramread.c
Normal file
102
src/core1/done/io/contramread.c
Normal 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;
|
||||
}
|
94
src/core1/done/io/contramwrite.c
Normal file
94
src/core1/done/io/contramwrite.c
Normal 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;
|
||||
}
|
75
src/core1/done/io/contreaddata.c
Normal file
75
src/core1/done/io/contreaddata.c
Normal 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;
|
||||
}
|
95
src/core1/done/io/controller.c
Normal file
95
src/core1/done/io/controller.c
Normal 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
207
src/core1/done/io/controller.h
Executable 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;
|
21
src/core1/done/io/contsetch.c
Normal file
21
src/core1/done/io/contsetch.c
Normal 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
47
src/core1/done/io/crc.c
Normal 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
113
src/core1/done/io/devmgr.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
src/core1/done/io/dpgetstat.c
Normal file
6
src/core1/done/io/dpgetstat.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <os_internal.h>
|
||||
#include <rcp.h>
|
||||
|
||||
u32 osDpGetStatus(){
|
||||
return IO_READ(DPC_STATUS_REG);
|
||||
}
|
7
src/core1/done/io/dpsetstat.c
Normal file
7
src/core1/done/io/dpsetstat.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <os_internal.h>
|
||||
#include <rcp.h>
|
||||
|
||||
void osDpSetStatus(u32 data)
|
||||
{
|
||||
IO_WRITE(DPC_STATUS_REG, data);
|
||||
}
|
66
src/core1/done/io/epirawdma.c
Normal file
66
src/core1/done/io/epirawdma.c
Normal 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;
|
||||
}
|
14
src/core1/done/io/epirawread.c
Normal file
14
src/core1/done/io/epirawread.c
Normal 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;
|
||||
}
|
13
src/core1/done/io/epirawwrite.c
Normal file
13
src/core1/done/io/epirawwrite.c
Normal 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;
|
||||
}
|
29
src/core1/done/io/leodiskinit.c
Normal file
29
src/core1/done/io/leodiskinit.c
Normal 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;
|
||||
}
|
215
src/core1/done/io/leointerrupt.c
Normal file
215
src/core1/done/io/leointerrupt.c
Normal 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
170
src/core1/done/io/motor.c
Normal 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;
|
||||
}
|
207
src/core1/done/io/pfschecker.c
Normal file
207
src/core1/done/io/pfschecker.c
Normal 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;
|
||||
}
|
26
src/core1/done/io/pfsgetstatus.c
Normal file
26
src/core1/done/io/pfsgetstatus.c
Normal 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;
|
||||
}
|
24
src/core1/done/io/pfsinit.c
Normal file
24
src/core1/done/io/pfsinit.c
Normal 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;
|
||||
}
|
99
src/core1/done/io/pfsisplug.c
Normal file
99
src/core1/done/io/pfsisplug.c
Normal 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
24
src/core1/done/io/piacs.c
Normal 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);
|
||||
}
|
11
src/core1/done/io/pigetcmdq.c
Normal file
11
src/core1/done/io/pigetcmdq.c
Normal 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
50
src/core1/done/io/pimgr.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
28
src/core1/done/io/pirawdma.c
Normal file
28
src/core1/done/io/pirawdma.c
Normal 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;
|
||||
}
|
11
src/core1/done/io/pirawread.c
Normal file
11
src/core1/done/io/pirawread.c
Normal 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
Reference in New Issue
Block a user