diff options
| author | Anghelo Carvajal <angheloalf95@gmail.com> | 2023-03-28 23:42:56 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-29 03:42:56 +0100 |
| commit | d66a21685f45d130f980e8a5ec7b08cfe189e40b (patch) | |
| tree | f11b3b09dc5772e419fe08d3d0ead4e778def57f /lib/ultralib/src | |
| parent | 6a5e64cc4c26398cc607bb02cdc12a056ddf42d1 (diff) | |
Initial repo setup (#1)
* git subrepo clone git@github.com:ethteck/splat.git tools/splat
subrepo:
subdir: "tools/splat"
merged: "4fec014"
upstream:
origin: "git@github.com:ethteck/splat.git"
branch: "master"
commit: "4fec014"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* gitignore
* decompress_baserom.py
* Initial yaml
* run flib
* more yaml stuff
* Builds an uncompressed ROM
* setup ido download
* git subrepo clone git@github.com:simonlindholm/asm-differ.git tools/asm-differ
subrepo:
subdir: "tools/asm-differ"
merged: "ae40866"
upstream:
origin: "git@github.com:simonlindholm/asm-differ.git"
branch: "main"
commit: "ae40866"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* git subrepo clone git@github.com:simonlindholm/asm-processor.git tools/asm-processor
subrepo:
subdir: "tools/asm-processor"
merged: "bbd86ea"
upstream:
origin: "git@github.com:simonlindholm/asm-processor.git"
branch: "main"
commit: "bbd86ea"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* git subrepo clone (merge) git@github.com:EllipticEllipsis/fado.git tools/fado
subrepo:
subdir: "tools/fado"
merged: "8d896ee"
upstream:
origin: "git@github.com:EllipticEllipsis/fado.git"
branch: "master"
commit: "8d896ee"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* setup ido in makefile
* data and rodata
* add automatic file splits
* bootstrap most symbol_addrs
* git subrepo clone --branch=irix git@github.com:hensldm/ultralib.git lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "0d1e095"
upstream:
origin: "git@github.com:hensldm/ultralib.git"
branch: "irix"
commit: "0d1e095"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* setup ido building
* various tooling
* git subrepo pull tools/asm-differ
subrepo:
subdir: "tools/asm-differ"
merged: "857b398"
upstream:
origin: "git@github.com:simonlindholm/asm-differ.git"
branch: "main"
commit: "857b398"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* Change defines to match IDO
* review
* newlin
* update gitignore
* Windows error
* D_01000000
* yeet settings.json
* yeet
* git subrepo clone git@github.com:decompals/ultralib.git lib/ultralib
subrepo:
subdir: "lib/ultralib"
merged: "d03b2a3"
upstream:
origin: "git@github.com:decompals/ultralib.git"
branch: "main"
commit: "d03b2a3"
git-subrepo:
version: "0.4.3"
origin: "https://github.com/ingydotnet/git-subrepo.git"
commit: "2f68596"
* clangformat and clangtidy
* Setup a bunch of headers
* bootstrap boot and code functions and variables headers
* global.h
* update format.py includes
* -D_MIPS_SZLONG=32
* format.py: --verbose
* Update tools/decompress_baserom.py
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
* Add libc to global.h
* review
* yeet saved_regs
* yeet headers
* yeet _MSC_VER
* more header cleanup
* add readme licensing note
---------
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Diffstat (limited to 'lib/ultralib/src')
513 files changed, 35517 insertions, 0 deletions
diff --git a/lib/ultralib/src/audio/Makefile b/lib/ultralib/src/audio/Makefile new file mode 100644 index 0000000..d8fdce4 --- /dev/null +++ b/lib/ultralib/src/audio/Makefile @@ -0,0 +1,120 @@ +#!smake +# +# Makefile for audio library subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + +# LCOPTS = -mips2 -non_shared -fullwarn -G 0 +LCINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include + +CFILES = \ + drvrnew.c \ + load.c \ + auxbus.c \ + bnkf.c \ + env.c \ + event.c \ + filter.c \ + mainbus.c \ + resample.c \ + reverb.c \ + save.c \ + seq.c \ + sl.c \ + heapcheck.c \ + heapinit.c \ + heapalloc.c \ + copy.c \ + seqpdelete.c \ + seqpgetfxmix.c \ + seqpgetpan.c \ + seqpgetchlvol.c \ + seqpgetpriority.c \ + seqpgetprogram.c \ + seqpgetseq.c \ + seqpgettempo.c \ + seqpgetvol.c \ + seqpgetstate.c \ + seqploop.c \ + seqpplay.c \ + seqpsendmidi.c \ + seqpsetbank.c \ + seqpsetfxmix.c \ + seqpsetpan.c \ + seqpsetchlvol.c \ + seqpsetpriority.c \ + seqpsetprogram.c \ + seqpsetseq.c \ + seqpsettempo.c \ + seqpsetvol.c \ + seqpstop.c \ + seqplayer.c \ + cseq.c \ + cspdelete.c \ + cspgetfxmix.c \ + cspgetpan.c \ + cspgetchlvol.c \ + cspgetpriority.c \ + cspgetprogram.c \ + cspgetseq.c \ + cspgettempo.c \ + cspgetvol.c \ + cspgetstate.c \ + cspplay.c \ + cspsendmidi.c \ + cspsetbank.c \ + cspsetfxmix.c \ + cspsetpan.c \ + cspsetchlvol.c \ + cspsetpriority.c \ + cspsetprogram.c \ + cspsetseq.c \ + cspsettempo.c \ + cspsetvol.c \ + cspstop.c \ + csplayer.c \ + sndplayer.c \ + sndpdelete.c \ + sndpallocate.c \ + sndpdeallocate.c \ + sndpsetsound.c \ + sndpplay.c \ + sndpplayat.c \ + sndpgetsound.c \ + sndpstop.c \ + sndpgetstate.c \ + sndpsetpitch.c \ + sndpsetpriority.c \ + sndpsetvol.c \ + sndpsetpan.c \ + sndpsetfxmix.c \ + synthesizer.c \ + syndelete.c \ + synaddplayer.c \ + synremoveplayer.c \ + synfreevoice.c \ + synallocvoice.c \ + synstopvoice.c \ + synstartvoice.c \ + synstartvoiceparam.c \ + synsetpitch.c \ + synsetvol.c \ + synsetfxmix.c \ + synsetpan.c \ + syngetpriority.c \ + synsetpriority.c \ + synallocfx.c \ + synfreefx.c \ + syngetfxref.c \ + synsetfxparam.c \ + cents2ratio.c \ + parse_abi.c + +TARGETS = $(CFILES:.c=.o) + +default : $(TARGETS) + +include $(COMMONRULES) + + diff --git a/lib/ultralib/src/audio/auxbus.c b/lib/ultralib/src/audio/auxbus.c new file mode 100644 index 0000000..471ba41 --- /dev/null +++ b/lib/ultralib/src/audio/auxbus.c @@ -0,0 +1,65 @@ +/*==================================================================== + * auxbus.c + * + * 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 <libaudio.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; + +} + diff --git a/lib/ultralib/src/audio/bnkf.c b/lib/ultralib/src/audio/bnkf.c new file mode 100644 index 0000000..dfd312f --- /dev/null +++ b/lib/ultralib/src/audio/bnkf.c @@ -0,0 +1,143 @@ +/*==================================================================== + * bnkf.c + * + * 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 <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> + +/* + * ### when the file format settles down a little, I'll remove these + * ### for efficiency. + */ +static void _bnkfPatchBank(ALBank *bank, s32 offset, s32 table); +static void _bnkfPatchInst(ALInstrument *i, s32 offset, s32 table); +static void _bnkfPatchSound(ALSound *s, s32 offset, s32 table); +static void _bnkfPatchWaveTable(ALWaveTable *w, s32 offset, s32 table); + +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); + } +} + +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); + } +} + +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 _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); + + } +} + +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); +} + +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); + } +} diff --git a/lib/ultralib/src/audio/cents2ratio.c b/lib/ultralib/src/audio/cents2ratio.c new file mode 100644 index 0000000..55cd2a3 --- /dev/null +++ b/lib/ultralib/src/audio/cents2ratio.c @@ -0,0 +1,33 @@ +/* + * alCents2Ratio() + * + * Calculates the pitch shift ratio from the number of cents according to + * ratio = 2^(cents/1200) + * + * This is accurate to within one cent for ratios up and octave and down + * two ocataves. + */ + +#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; +} diff --git a/lib/ultralib/src/audio/copy.c b/lib/ultralib/src/audio/copy.c new file mode 100644 index 0000000..e80a8df --- /dev/null +++ b/lib/ultralib/src/audio/copy.c @@ -0,0 +1,35 @@ +/*==================================================================== + * copy.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.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++; + } +} + diff --git a/lib/ultralib/src/audio/cseq.c b/lib/ultralib/src/audio/cseq.c new file mode 100644 index 0000000..9c4b8bd --- /dev/null +++ b/lib/ultralib/src/audio/cseq.c @@ -0,0 +1,409 @@ +/*==================================================================== + * cseq.c + * + * 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 <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> +#include "cseq.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); +} + + + + + + + + + + diff --git a/lib/ultralib/src/audio/cseq.h b/lib/ultralib/src/audio/cseq.h new file mode 100644 index 0000000..0342398 --- /dev/null +++ b/lib/ultralib/src/audio/cseq.h @@ -0,0 +1,11 @@ + + + +#ifndef __cseq__ +#define __cseq__ + + +char __alCSeqNextDelta(ALCSeq *seq, s32 *pDeltaTicks); + + +#endif /* __cseq__ */ diff --git a/lib/ultralib/src/audio/cseqp.h b/lib/ultralib/src/audio/cseqp.h new file mode 100644 index 0000000..bb72541 --- /dev/null +++ b/lib/ultralib/src/audio/cseqp.h @@ -0,0 +1,10 @@ + + +#ifndef __cseqp__ +#define __cseqp__ + + +void __CSPPostNextSeqEvent(ALCSPlayer *seqp); + + +#endif /* __cseqp__ */ diff --git a/lib/ultralib/src/audio/cspdelete.c b/lib/ultralib/src/audio/cspdelete.c new file mode 100644 index 0000000..063c543 --- /dev/null +++ b/lib/ultralib/src/audio/cspdelete.c @@ -0,0 +1,29 @@ +/*==================================================================== + * cspdelete.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPDelete(ALCSPlayer *seqp) +{ + alSynRemovePlayer(seqp->drvr, &seqp->node); +} + diff --git a/lib/ultralib/src/audio/cspgetchlvol.c b/lib/ultralib/src/audio/cspgetchlvol.c new file mode 100644 index 0000000..23d256e --- /dev/null +++ b/lib/ultralib/src/audio/cspgetchlvol.c @@ -0,0 +1,27 @@ +/*==================================================================== + * cspgetchlvol.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alCSPGetChlVol(ALCSPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].vol; +} + diff --git a/lib/ultralib/src/audio/cspgetfxmix.c b/lib/ultralib/src/audio/cspgetfxmix.c new file mode 100644 index 0000000..c67e033 --- /dev/null +++ b/lib/ultralib/src/audio/cspgetfxmix.c @@ -0,0 +1,27 @@ +/*==================================================================== + * cspgetfxmix.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alCSPGetChlFXMix(ALCSPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].fxmix; +} + diff --git a/lib/ultralib/src/audio/cspgetpan.c b/lib/ultralib/src/audio/cspgetpan.c new file mode 100644 index 0000000..5c0e322 --- /dev/null +++ b/lib/ultralib/src/audio/cspgetpan.c @@ -0,0 +1,27 @@ +/*==================================================================== + * cspgetpan.c + * + * Copyright 1995, 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 <libaudio.h> + +ALPan alCSPGetChlPan(ALCSPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].pan; +} + diff --git a/lib/ultralib/src/audio/cspgetpriority.c b/lib/ultralib/src/audio/cspgetpriority.c new file mode 100644 index 0000000..ac38cae --- /dev/null +++ b/lib/ultralib/src/audio/cspgetpriority.c @@ -0,0 +1,26 @@ +/*==================================================================== + * cspgetpriority.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alCSPGetChlPriority(ALCSPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].priority; +} diff --git a/lib/ultralib/src/audio/cspgetprogram.c b/lib/ultralib/src/audio/cspgetprogram.c new file mode 100644 index 0000000..382616f --- /dev/null +++ b/lib/ultralib/src/audio/cspgetprogram.c @@ -0,0 +1,42 @@ +/*==================================================================== + * cspgetprogram.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +s32 alCSPGetChlProgram(ALCSPlayer *seqp, u8 chan) + +{ + s32 i; + ALBank *b = seqp->bank; + ALInstrument *inst; + ALChanState s; + + s = seqp->chanState[chan]; + for (i=0; i<b->instCount; i++){ + inst = b->instArray[i]; + if (inst == s.instrument) + return i; + } + return(-1); + +} + diff --git a/lib/ultralib/src/audio/cspgetseq.c b/lib/ultralib/src/audio/cspgetseq.c new file mode 100644 index 0000000..85d2545 --- /dev/null +++ b/lib/ultralib/src/audio/cspgetseq.c @@ -0,0 +1,29 @@ +/*==================================================================== + * cspgetseq.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +ALCSeq *alCSPGetSeq(ALCSPlayer *seqp) +{ + return seqp->target; +} + diff --git a/lib/ultralib/src/audio/cspgetstate.c b/lib/ultralib/src/audio/cspgetstate.c new file mode 100644 index 0000000..9be7937 --- /dev/null +++ b/lib/ultralib/src/audio/cspgetstate.c @@ -0,0 +1,29 @@ +/*==================================================================== + * cspgetstate.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +s32 alCSPGetState(ALCSPlayer *seqp) +{ + return seqp->state; +} + diff --git a/lib/ultralib/src/audio/cspgettempo.c b/lib/ultralib/src/audio/cspgettempo.c new file mode 100644 index 0000000..ed3dfe2 --- /dev/null +++ b/lib/ultralib/src/audio/cspgettempo.c @@ -0,0 +1,31 @@ +/*==================================================================== + * cspgettempo.c + * + * Copyright 1995, 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 <libaudio.h> + +s32 alCSPGetTempo(ALCSPlayer *seqp) +{ + /* sct 1/8/96 - If no target sequence has been set, just return zero (instead of crashing). */ + if (seqp->target == NULL) + return 0; + + return seqp->uspt/seqp->target->qnpt; +} + diff --git a/lib/ultralib/src/audio/cspgetvol.c b/lib/ultralib/src/audio/cspgetvol.c new file mode 100644 index 0000000..5353228 --- /dev/null +++ b/lib/ultralib/src/audio/cspgetvol.c @@ -0,0 +1,27 @@ +/*==================================================================== + * cspgetvol.c + * + * Copyright 1995, 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 <libaudio.h> + +s16 alCSPGetVol(ALCSPlayer *seqp) +{ + return seqp->vol; +} + diff --git a/lib/ultralib/src/audio/csplayer.c b/lib/ultralib/src/audio/csplayer.c new file mode 100644 index 0000000..621ce02 --- /dev/null +++ b/lib/ultralib/src/audio/csplayer.c @@ -0,0 +1,886 @@ +/*==================================================================== + * csplayer.c + * + * Copyright 1995, 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. + *====================================================================*/ + +/* + * Notes: + * + * Controller Numbers: + * 1 Modulation + * 7 Volume + * 10 Pan + * 11 Expression + * 64 Sustain + * 121 Reset All Controllers + * 123 All Notes Off + * + * Registered Parameters + * 0 Pitch Bend Sensitivity + * 1 Fine Tuning + * 2 Coarse Tuning + */ + +#include <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> +#include <assert.h> +#include "seqp.h" +#include "cseqp.h" +#include "cseq.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + + +static ALMicroTime __CSPVoiceHandler(void *node); +static void __CSPHandleNextSeqEvent(ALCSPlayer *seqp); +static void __CSPHandleMIDIMsg(ALCSPlayer *seqp, ALEvent *event); +static void __CSPHandleMetaMsg(ALCSPlayer *seqp, ALEvent *event); +static void __CSPRepostEvent(ALEventQueue *evtq, ALEventListItem *item); +static void __setUsptFromTempo(ALCSPlayer *seqp, f32 tempo); /* sct 1/8/96 */ + + +/* + * Sequence Player public functions + */ +void alCSPNew(ALCSPlayer *seqp, ALSeqpConfig *c) +{ + s32 i; + ALEventListItem *items; + ALVoiceState *vs; + ALVoiceState *voices; + + ALHeap *hp = c->heap; + + /* + * initialize member variables + */ + seqp->bank = 0; + seqp->target = NULL; + seqp->drvr = &alGlobals->drvr; + seqp->chanMask = 0xff; + seqp->uspt = 488; + seqp->nextDelta = 0; + seqp->state = AL_STOPPED; + seqp->vol = 0x7FFF; /* full volume */ + 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 = __CSPVoiceHandler; + seqp->node.clientData = seqp; + alSynAddPlayer(&alGlobals->drvr, &seqp->node); +} + +/************************************************************* + * private routines or driver callback routines + *************************************************************/ +static ALMicroTime __CSPVoiceHandler(void *node) +{ + ALCSPlayer *seqp = (ALCSPlayer *) node; + ALEvent evt; + ALVoice *voice; + ALMicroTime delta; + ALVoiceState *vs; + void *oscState; + f32 oscValue; + u8 chan; + + do { + switch (seqp->nextEvent.type) + { + case (AL_SEQ_REF_EVT): + __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; + + alSynStopVoice(seqp->drvr, voice); + alSynFreeVoice(seqp->drvr, 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; + alSynSetVol(seqp->drvr, 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; + alSynSetVol(seqp->drvr, &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; + alSynSetPitch(seqp->drvr, &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 */ + __CSPHandleMIDIMsg(seqp, &seqp->nextEvent); + break; + + case (AL_SEQP_META_EVT): + __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) + { + alSynSetVol(seqp->drvr, &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; + __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 + alSynStopVoice(seqp->drvr, &vs->voice); + alSynFreeVoice(seqp->drvr, &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): + +#ifdef _DEBUG + assert(seqp->state != AL_PLAYING); /* Must be done playing to change sequences. */ +#endif + + seqp->target = seqp->nextEvent.msg.spseq.seq; + __setUsptFromTempo (seqp, 500000.0); + if (seqp->bank) + __initFromBank((ALSeqPlayer *)seqp, seqp->bank); + break; + + case (AL_SEQP_BANK_EVT): + +#ifdef _DEBUG + assert(seqp->state == AL_STOPPED); /* Must be fully stopped to change banks. */ +#endif + + seqp->bank = seqp->nextEvent.msg.spbank.bank; + __initFromBank((ALSeqPlayer *)seqp, seqp->bank); + break; + + /* sct 11/6/95 - these events should now be handled by __CSPHandleNextSeqEvent */ + case (AL_SEQ_END_EVT): + case (AL_TEMPO_EVT): + case (AL_SEQ_MIDI_EVT): + +#ifdef _DEBUG + assert(FALSE); +#endif + + 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 +*/ +void __CSPPostNextSeqEvent(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 +__CSPHandleNextSeqEvent(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: + __CSPHandleMIDIMsg(seqp, &evt); + __CSPPostNextSeqEvent(seqp); + break; + + case AL_TEMPO_EVT: + __CSPHandleMetaMsg(seqp, &evt); + __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: + __CSPPostNextSeqEvent(seqp); + break; + + default: + +#ifdef _DEBUG + assert(FALSE); /* Sequence event type not supported. */ +#endif + + break; + } +} + + +static void __CSPHandleMIDIMsg(ALCSPlayer *seqp, ALEvent *event) +{ + ALVoice *voice; + ALVoiceState *vs; + s32 status; + u8 chan; + u8 key; + u8 vel; + u8 byte1; + u8 byte2; + ALMIDIEvent *midi = &event->msg.midi; + s16 vol; + ALEvent evt; + ALMicroTime deltaTime; + 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; + + 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; + + alSynAllocVoice(seqp->drvr, 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; + + alSynStartVoiceParams(seqp->drvr, 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; + alSynSetVol(seqp->drvr, &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; + alSynSetVol(seqp->drvr, &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); + alSynSetPan(seqp->drvr, &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); + alSynSetVol(seqp->drvr, &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) + alSynSetFXMix(seqp->drvr, &vs->voice, byte2); + } + break; +/* case (AL_MIDI_FX_CTRL_0): + case (AL_MIDI_FX_CTRL_1): + case (AL_MIDI_FX_CTRL_2): + case (AL_MIDI_FX_CTRL_3): + case (AL_MIDI_FX_CTRL_4): + case (AL_MIDI_FX_CTRL_5): + case (AL_MIDI_FX_CTRL_6): + case (AL_MIDI_FX_CTRL_7): + fxref = alSynGetFXRef(seqp->drvr, 0, 0); + if (fxref) + alSynSetFXParam(seqp->drvr, fxref, (s16)byte1, (void *)byte2); + break; + case (AL_MIDI_FX3_CTRL): */ + default: + break; + } + break; + case (AL_MIDI_ProgramChange): + /* sct 1/16/96 - We must have a valid bank in order to process the program change. */ + +#ifdef _DEBUG + assert(seqp->bank != NULL); +#endif + + 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) + alSynSetPitch(seqp->drvr, &vs->voice, + vs->pitch * bendRatio * vs->vibrato); + + } + break; + + default: +#ifdef _DEBUG + __osError(ERR_ALSEQPUNKNOWNMIDI, 1, status); +#endif + break; + } + +} + +static void __CSPHandleMetaMsg(ALCSPlayer *seqp, 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); + __setUsptFromTempo (seqp, (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; + __CSPRepostEvent(&seqp->evtq,thisNode); + thisNode = nextNode; + } + } + } +} + +static void __CSPRepostEvent(ALEventQueue *evtq, ALEventListItem *item) +{ + OSIntMask mask; + ALLink *node; + 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 = (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. +*/ +static void __setUsptFromTempo (ALCSPlayer *seqp, f32 tempo) +{ + if (seqp->target) + seqp->uspt = (s32)((f32)tempo * seqp->target->qnpt); + else + seqp->uspt = 488; /* This is the initial value set by alSeqpNew. */ +} + diff --git a/lib/ultralib/src/audio/cspplay.c b/lib/ultralib/src/audio/cspplay.c new file mode 100644 index 0000000..e34914c --- /dev/null +++ b/lib/ultralib/src/audio/cspplay.c @@ -0,0 +1,34 @@ +/*==================================================================== + * cspplay.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> +#include "cseqp.h" + +void alCSPPlay(ALCSPlayer *seqp) +{ + ALEvent evt; + + evt.type = AL_SEQP_PLAY_EVT; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/cspsendmidi.c b/lib/ultralib/src/audio/cspsendmidi.c new file mode 100644 index 0000000..3d03c9b --- /dev/null +++ b/lib/ultralib/src/audio/cspsendmidi.c @@ -0,0 +1,40 @@ +/*==================================================================== + * cspsendmidi.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSendMidi(ALCSPlayer *seqp, s32 ticks, u8 status, u8 byte1, + u8 byte2) +{ + ALEvent evt; + ALMicroTime deltaTime; + + evt.type = AL_SEQP_MIDI_EVT; + evt.msg.midi.ticks = 0; + evt.msg.midi.status = status; + evt.msg.midi.byte1 = byte1; + evt.msg.midi.byte2 = byte2; + evt.msg.midi.duration = 0; + + deltaTime = ticks*seqp->uspt; + + alEvtqPostEvent(&seqp->evtq, &evt, deltaTime); +} + diff --git a/lib/ultralib/src/audio/cspsetbank.c b/lib/ultralib/src/audio/cspsetbank.c new file mode 100644 index 0000000..63292b4 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetbank.c @@ -0,0 +1,32 @@ +/*==================================================================== + * cspsetbank.c + * + * Copyright 1995, 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 <libaudio.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); +} + diff --git a/lib/ultralib/src/audio/cspsetchlvol.c b/lib/ultralib/src/audio/cspsetchlvol.c new file mode 100644 index 0000000..28e62bb --- /dev/null +++ b/lib/ultralib/src/audio/cspsetchlvol.c @@ -0,0 +1,35 @@ +/*==================================================================== + * cspsetchlvol.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSetChlVol(ALCSPlayer *seqp, u8 chan, u8 vol) +{ + 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 = AL_MIDI_VOLUME_CTRL; + evt.msg.midi.byte2 = vol; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/cspsetfxmix.c b/lib/ultralib/src/audio/cspsetfxmix.c new file mode 100644 index 0000000..f099297 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetfxmix.c @@ -0,0 +1,35 @@ +/*==================================================================== + * cspsetfxmix.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSetChlFXMix(ALCSPlayer *seqp, u8 chan, u8 fxmix) +{ + 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 = AL_MIDI_FX1_CTRL; + evt.msg.midi.byte2 = fxmix; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/cspsetpan.c b/lib/ultralib/src/audio/cspsetpan.c new file mode 100644 index 0000000..c0dab00 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetpan.c @@ -0,0 +1,35 @@ +/*==================================================================== + * cspsetpan.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSetChlPan(ALCSPlayer *seqp, u8 chan, ALPan pan) +{ + 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 = AL_MIDI_PAN_CTRL; + evt.msg.midi.byte2 = pan; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/cspsetpriority.c b/lib/ultralib/src/audio/cspsetpriority.c new file mode 100644 index 0000000..b449b82 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetpriority.c @@ -0,0 +1,32 @@ +/*==================================================================== + * cspsetpriority.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSetChlPriority(ALCSPlayer *seqp, u8 chan, u8 priority) +{ + ALEvent evt; + + evt.type = AL_SEQP_PRIORITY_EVT; + evt.msg.sppriority.chan = chan; + evt.msg.sppriority.priority = priority; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} diff --git a/lib/ultralib/src/audio/cspsetprogram.c b/lib/ultralib/src/audio/cspsetprogram.c new file mode 100644 index 0000000..2b19e63 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetprogram.c @@ -0,0 +1,35 @@ +/*==================================================================== + * cspsetprogram.c + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPSetChlProgram(ALCSPlayer *seqp, u8 chan, u8 prog) +{ + ALEvent evt; + + evt.type = AL_SEQP_MIDI_EVT; + evt.msg.midi.ticks = 0; + evt.msg.midi.status = AL_MIDI_ProgramChange | chan; + evt.msg.midi.byte1 = prog; + evt.msg.midi.byte2 = 0; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/cspsetseq.c b/lib/ultralib/src/audio/cspsetseq.c new file mode 100644 index 0000000..4b6718e --- /dev/null +++ b/lib/ultralib/src/audio/cspsetseq.c @@ -0,0 +1,34 @@ +/*==================================================================== + * cspsetseq.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.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); +} + diff --git a/lib/ultralib/src/audio/cspsettempo.c b/lib/ultralib/src/audio/cspsettempo.c new file mode 100644 index 0000000..b085b45 --- /dev/null +++ b/lib/ultralib/src/audio/cspsettempo.c @@ -0,0 +1,36 @@ +/*==================================================================== + * cspsettempo.c + * + * Copyright 1995, 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 <libaudio.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); +} + diff --git a/lib/ultralib/src/audio/cspsetvol.c b/lib/ultralib/src/audio/cspsetvol.c new file mode 100644 index 0000000..6782f33 --- /dev/null +++ b/lib/ultralib/src/audio/cspsetvol.c @@ -0,0 +1,32 @@ +/*==================================================================== + * cspsetvol.c + * + * Copyright 1995, 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 <libaudio.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); +} + diff --git a/lib/ultralib/src/audio/cspstop.c b/lib/ultralib/src/audio/cspstop.c new file mode 100644 index 0000000..9929820 --- /dev/null +++ b/lib/ultralib/src/audio/cspstop.c @@ -0,0 +1,32 @@ +/*==================================================================== + * cspstop.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +void alCSPStop(ALCSPlayer *seqp) +{ + ALEvent evt; + + evt.type = AL_SEQP_STOPPING_EVT; + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/drvrnew.c b/lib/ultralib/src/audio/drvrnew.c new file mode 100644 index 0000000..ef9e27f --- /dev/null +++ b/lib/ultralib/src/audio/drvrnew.c @@ -0,0 +1,306 @@ +/*==================================================================== + * drvrNew.c + * + * 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 <libaudio.h> +#include "synthInternals.h" +#include <os.h> +#include <stdio.h> +#include "initfx.h" + +// TODO: this comes from a header +#ident "$Revision: 1.49 $" + +/* + * 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; + +} + diff --git a/lib/ultralib/src/audio/env.c b/lib/ultralib/src/audio/env.c new file mode 100644 index 0000000..bc7369a --- /dev/null +++ b/lib/ultralib/src/audio/env.c @@ -0,0 +1,595 @@ +/*==================================================================== + * envmixer.c + * + * 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 <libaudio.h> +#include "synthInternals.h" +#include <os.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> + +// TODO: these come from headers +#ident "$Revision: 1.49 $" +#ident "$Revision: 1.17 $" + +#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; + +#ifdef _DEBUG + assert(samples >= 0); + assert(samples <= AL_MAX_RSP_SAMPLES); +#endif + + 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) >> 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); + + 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; + 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->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); + + } + + ptr = _pullSubFrame(e, &inp, &loutp, outCount, sampleOffset, ptr); + + /* + * 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; + + /* + * ask all filters upstream from us to build their command + * lists. + */ +#ifdef _DEBUG + assert(source); +#endif + + 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 invn = 1.0/count, eps, a, fs, mant; + s32 i_invn, ex, indx; + +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + + if (count == 0){ + if (tgt >= vol){ + *ratel = 0xffff; + return 0x7fff; + } + else{ + *ratel = 0; + return 0; + } + } + + if (tgt < 1.0) + tgt = 1.0; + if (vol <= 0) vol = 1; /* zero and neg values not allowed */ + +#define NBITS (3) +#define NPOS (1<<NBITS) +#define NFRACBITS (30) +#define M_LN2 0.69314718055994530942 + /* + * rww's parametric pow() + Goal: compute a = (tgt/vol)^(1/count) + + Approach: + (tgt/vol)^(1/count) = + ((tgt/vol)^(1/2^30))^(2^30*1/count) + + (tgt/vol)^(1/2^30) ~= 1 + eps + + where + + eps ~= ln(tgt/vol)/2^30 + + ln(tgt/vol) = ln2(tgt/vol) * ln(2) + + ln2(tgt/vol) = fp_exponent( tgt/vol ) + + ln2( fp_mantissa( tgt/vol ) ) + + fp_mantissa() and fp_exponent() are + calculated via tricky bit manipulations of + the floating point number. ln2() is + approximated by a look up table. + + Note that this final (1+eps) value needs + to be raised to the 2^30/count power. This + is done by operating on the binary representaion + of this number in the final while loop. + + Enjoy! + */ + { + f64 logtab[] = { -0.912537, -0.752072, -0.607683, -0.476438, + -0.356144, -0.245112, -0.142019, -0.045804 }; + + i_invn = (s32) _ldexpf( invn, NFRACBITS ); + mant = _frexpf( tgt/vol, &ex ); + indx = (s32) (_ldexpf( mant, NBITS+1 ) ); /* NPOS <= indx < 2*NPOS */ + eps = (logtab[indx - NPOS] + ex) * M_LN2; + eps /= _ldexpf( 1, NFRACBITS ); /* eps / 2^NFRACBITS */ + fs = (1.0 + eps); + a = 1.0; + while( i_invn ) { + if( i_invn & 1 ) + a = a * fs; + fs *= fs; + i_invn >>= 1; + } + } + + a *= (a *= (a *= a)); + 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, a; + s32 i; + +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + + /* + * Rate values are actually rate^8 + */ + samples >>=3; + if (samples == 0){ + return ivol; + } + r = ((f32) (ratem<<16) + (f32) ratel)/65536; + + a = 1.0; + for (i=0; i<32; i++){ + if( samples & 1 ) + a *= r; + samples >>= 1; + if (samples == 0) + break; + r *= r; + } + ivol *= a; +#ifdef AUD_PROFILE + PROFILE_AUD(vol_num, vol_cnt, vol_max, vol_min); +#endif + return ivol; +} + + + + + + + diff --git a/lib/ultralib/src/audio/event.c b/lib/ultralib/src/audio/event.c new file mode 100644 index 0000000..3112c99 --- /dev/null +++ b/lib/ultralib/src/audio/event.c @@ -0,0 +1,272 @@ +/*==================================================================== + * event.c + * + * 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 <libaudio.h> +#include <os_internal.h> +#include <ultraerror.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; + + for (i = 0; i < itemCount; i++) { + alLink((ALLink *)&items[i], &evtq->freeList); + } +} + +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); +#ifdef _DEBUG + __osError(ERR_ALEVENTNOFREE, 0); +#endif + return; + } + + alUnlink((ALLink *)item); + alCopy(evt, &item->evt, sizeof(*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((ALLink *)item, node); + break; + } else { + nextItem = (ALEventListItem *)node->next; + + if (delta < nextItem->delta) { + item->delta = delta; + nextItem->delta -= delta; + + alLink((ALLink *)item, node); + break; + } + + delta -= nextItem->delta; + + } + } + + osSetIntMask(mask); + +} + +void alEvtqFlush(ALEventQueue *evtq) +{ + ALLink *thisNode; + ALLink *nextNode; + OSIntMask mask; + + mask = osSetIntMask(OS_IM_NONE); + + thisNode = evtq->allocList.next; + while( thisNode != 0 ) { + nextNode = thisNode->next; + alUnlink(thisNode); + alLink(thisNode, &evtq->freeList); + thisNode = nextNode; + } + + osSetIntMask(mask); +} + + +/* + This routine flushes events according their type. +*/ +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); +} + + +#ifdef _DEBUG_INTERNAL +void alEvtqPrintEvtQueue(ALEventQueue *evtq) +{ + s32 count1 = 0; + s32 count2 = 0; + ALLink *node; + ALEventListItem *item; + + /* count free events */ + for (node = evtq->freeList.next; node != 0; node= node->next) { + count1++; + } + + PRINTF("----- Allocated Events -----\n"); + for (node = evtq->allocList.next; node != 0; node= node->next) { + item = (ALEventListItem *)node; + + PRINTF("\tdelta: %d\ttype %d\n", item->delta, item->evt.type); + count2++; + } + PRINTF("\n"); + + PRINTF("free events\t %d\n", count1); + PRINTF("alloc events\t %d\n", count2); + PRINTF("total events\t %d\n", count1 + count2); +} + +char *MidiStatus2Str (char status, char *str); + +void +alEvtqPrintAllocEvts(ALEventQueue *evtq) +{ + ALLink *node; + ALEventListItem *item; + ALMicroTime itemTime = 0; + char str[32]; + + PRINTF("----- Allocated Events -----\n"); + for (node = evtq->allocList.next; node != 0; node= node->next) + { + item = (ALEventListItem *)node; + itemTime += item->delta; + + PRINTF("\tdelta: %d\tabs: %d\t", item->delta, itemTime); + + switch (item->evt.type) + { + case AL_NOTE_END_EVT: + PRINTF("NOTE_END\tvox: %x\n", item->evt.msg.note.voice); + break; + + case AL_SEQP_MIDI_EVT: + PRINTF("SEQP_MIDI\t%s\n", MidiStatus2Str(item->evt.msg.midi.status & AL_MIDI_StatusMask, str)); + break; + + case AL_SEQP_PRIORITY_EVT: + PRINTF("SEQP_PRIORITY\n"); + break; + + default: + PRINTF("type: %d\n", item->evt.type); + break; + } + + } + PRINTF("\n"); + +} + +char * +MidiStatus2Str (char status, char *str) +{ + switch (status) + { + case AL_MIDI_NoteOn: + sprintf(str, "note on"); + break; + + case AL_MIDI_NoteOff: + sprintf(str, "note off"); + break; + + default: + sprintf(str, "status:%d", status); + break; + } + + return str; +} + +#endif /* _DEBUG_INTERNAL */ + + + diff --git a/lib/ultralib/src/audio/filter.c b/lib/ultralib/src/audio/filter.c new file mode 100644 index 0000000..d88460b --- /dev/null +++ b/lib/ultralib/src/audio/filter.c @@ -0,0 +1,32 @@ +/*==================================================================== + * filter.c + * + * 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 <libaudio.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; +} diff --git a/lib/ultralib/src/audio/heapalloc.c b/lib/ultralib/src/audio/heapalloc.c new file mode 100644 index 0000000..8a37808 --- /dev/null +++ b/lib/ultralib/src/audio/heapalloc.c @@ -0,0 +1,65 @@ +/*==================================================================== + * heapalloc.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <libaudio.h> +#include <os_internal.h> +#include <ultraerror.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; +} diff --git a/lib/ultralib/src/audio/heapcheck.c b/lib/ultralib/src/audio/heapcheck.c new file mode 100644 index 0000000..baae643 --- /dev/null +++ b/lib/ultralib/src/audio/heapcheck.c @@ -0,0 +1,71 @@ +/*==================================================================== + * heapcheck.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> + +#ifdef AUD_PROFILE +#include <os.h> +extern u32 cnt_index, heap_num, heap_cnt, heap_max, heap_min, lastCnt[]; +#endif + +s32 alHeapCheck(ALHeap *hp) +{ + s32 rv = 0; + HeapInfo *hi; + HeapInfo *last = 0; + u8 *ptr; + +#ifdef AUD_PROFILE + lastCnt[++cnt_index] = osGetCount(); +#endif + +#ifdef _DEBUG + for (ptr = hp->base; ptr < hp->cur; ptr += hi->size){ + + hi = (HeapInfo *)ptr; + + if ( hi->magic != AL_HEAP_MAGIC) { + if (last) { + __osError(ERR_ALHEAPCORRUPT, 0); + } else { + __osError(ERR_ALHEAPFIRSTBLOCK, 0); + } + + rv = 1; +#ifdef AUD_PROFILE + PROFILE_AUD(heap_num, heap_cnt, heap_max, heap_min); +#endif + return rv; + } + + last = hi; + + } +#endif +#ifdef AUD_PROFILE + PROFILE_AUD(heap_num, heap_cnt, heap_max, heap_min); +#endif + return rv; +} + + diff --git a/lib/ultralib/src/audio/heapinit.c b/lib/ultralib/src/audio/heapinit.c new file mode 100644 index 0000000..9053375 --- /dev/null +++ b/lib/ultralib/src/audio/heapinit.c @@ -0,0 +1,37 @@ +/*==================================================================== + * heapinit.c + * + * Copyright 1995, 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 "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; +} + diff --git a/lib/ultralib/src/audio/initfx.h b/lib/ultralib/src/audio/initfx.h new file mode 100644 index 0000000..704e1f4 --- /dev/null +++ b/lib/ultralib/src/audio/initfx.h @@ -0,0 +1,59 @@ +/*==================================================================== + * initfx.h + * + * 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. + *====================================================================*/ + +#ifndef __initfx__ +#define __initfx__ + +#define MAX_L0 AL_FX_BUFFER_SIZE/4 +#define MAX_L1 AL_FX_BUFFER_SIZE/4 +#define MAX_L2 AL_FX_BUFFER_SIZE/2 + +#define L0_INC MAX_L0/128 +#define L1_INC MAX_L1/128 +#define L2_INC MAX_L2/128 + +#define SMALLROOM_SECT_CNT 3 +#define SMALLROOM_SIZE AL_FX_BUFFER_SIZE +#define SMALLROOM_L0 880 /* 22 ms */ +#define SMALLROOM_C0 9830 +#define SMALLROOM_L1 1400 /* 35 ms */ +#define SMALLROOM_C1 3276 +#define SMALLROOM_L2 2640 /* 66 ms */ +#define SMALLROOM_C2 10000 +#define SMALLROOM_FILT_CNT 1 +#define SMALLROOM_FC0 0x4000 /* .25 */ + +#define BIGROOM_SECT_CNT 3 +#define BIGROOM_SIZE AL_FX_BUFFER_SIZE +#define BIGROOM_L0 1408 /* 32 ms */ +#define BIGROOM_C0 9830 +#define BIGROOM_L1 1984 /* 45 ms */ +#define BIGROOM_C1 9830 +#define BIGROOM_L2 3792 /* 86 ms */ +#define BIGROOM_C2 12000 +#define BIGROOM_FILT_CNT 1 +#define BIGROOM_FC0 0x4000 /* .25 */ + +#define ECHO_SIZE AL_FX_BUFFER_SIZE +#define ECHO_SECT_CNT 1 +#define ECHO_L0 7936 /* 180 ms */ +#define ECHO_C0 0x6000 + +#endif diff --git a/lib/ultralib/src/audio/load.c b/lib/ultralib/src/audio/load.c new file mode 100644 index 0000000..af07075 --- /dev/null +++ b/lib/ultralib/src/audio/load.c @@ -0,0 +1,471 @@ +/*==================================================================== + * load.c + * + * 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 <libaudio.h> +#include "synthInternals.h" +#include <os.h> +#include <R4300.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; +} + + + diff --git a/lib/ultralib/src/audio/mainbus.c b/lib/ultralib/src/audio/mainbus.c new file mode 100644 index 0000000..d5c8eca --- /dev/null +++ b/lib/ultralib/src/audio/mainbus.c @@ -0,0 +1,67 @@ +/*==================================================================== + * mainbus.c + * + * 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 <libaudio.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; + +} + diff --git a/lib/ultralib/src/audio/parse_abi.c b/lib/ultralib/src/audio/parse_abi.c new file mode 100644 index 0000000..f1fd37d --- /dev/null +++ b/lib/ultralib/src/audio/parse_abi.c @@ -0,0 +1,47 @@ +#include <ultra64.h> +#include <libaudio.h> +#include <ultrahost.h> +#include <gu.h> + +#ifndef _FINALROM +void alParseAbiCL(Acmd *cmdList, u32 nbytes) +{ + guDLPrintCB cntlBlk; + + cntlBlk.dataSize = nbytes; + cntlBlk.flags = 0; + cntlBlk.dlType = GU_PARSE_ABI_TYPE; + cntlBlk.paddr = osVirtualToPhysical(cmdList); + + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost(cmdList,nbytes); + +} + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/ultralib/src/audio/resample.c b/lib/ultralib/src/audio/resample.c new file mode 100644 index 0000000..2baf26f --- /dev/null +++ b/lib/ultralib/src/audio/resample.c @@ -0,0 +1,150 @@ +/*==================================================================== + * resample.c + * + * 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 <libaudio.h> +#include "synthInternals.h" +#include <os.h> +#include <stdio.h> + +// TODO: this comes from a header +#ident "$Revision: 1.49 $" + +#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; +} diff --git a/lib/ultralib/src/audio/reverb.c b/lib/ultralib/src/audio/reverb.c new file mode 100644 index 0000000..292ed0f --- /dev/null +++ b/lib/ultralib/src/audio/reverb.c @@ -0,0 +1,457 @@ +/*==================================================================== + * reverb.c + * + * 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 <libaudio.h> +#include <ultraerror.h> +#include "synthInternals.h" +#include <os.h> +#include <os_internal.h> +#include <stdio.h> +#include <assert.h> +#include "initfx.h" + +// TODO: these come from headers +#ident "$Revision: 1.49 $" +#ident "$Revision: 1.17 $" + +#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 + +#ifdef _DEBUG + assert(source); +#endif + + /* + * 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); +} + + + diff --git a/lib/ultralib/src/audio/save.c b/lib/ultralib/src/audio/save.c new file mode 100644 index 0000000..bc15294 --- /dev/null +++ b/lib/ultralib/src/audio/save.c @@ -0,0 +1,73 @@ +/*==================================================================== + * save.c + * + * 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 <libaudio.h> +#include "synthInternals.h" +#include <os.h> +#include <assert.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +Acmd *alSavePull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, + Acmd *p) + +{ + Acmd *ptr = p; + ALSave *f = (ALSave *)filter; + ALFilter *source = f->filter.source; + +#ifdef _DEBUG + assert(f->filter.source); +#endif + + 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; + +} + + + diff --git a/lib/ultralib/src/audio/seq.c b/lib/ultralib/src/audio/seq.c new file mode 100644 index 0000000..5da5b11 --- /dev/null +++ b/lib/ultralib/src/audio/seq.c @@ -0,0 +1,343 @@ +/*==================================================================== + * seq.c + * + * 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 <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> +#include "seq.h" + + +#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); +} + + + + + + + + + + diff --git a/lib/ultralib/src/audio/seq.h b/lib/ultralib/src/audio/seq.h new file mode 100644 index 0000000..479b339 --- /dev/null +++ b/lib/ultralib/src/audio/seq.h @@ -0,0 +1,9 @@ + + +#ifndef __seq__ +#define __seq__ + +char __alSeqNextDelta (ALSeq *seq, s32 *pDeltaTicks); + + +#endif /* __seq__ */ diff --git a/lib/ultralib/src/audio/seqp.h b/lib/ultralib/src/audio/seqp.h new file mode 100644 index 0000000..c9ab02b --- /dev/null +++ b/lib/ultralib/src/audio/seqp.h @@ -0,0 +1,37 @@ + + +#define KILL_TIME 50000 /* 50 ms */ + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +ALVoiceState *__mapVoice(ALSeqPlayer *, u8, u8, u8); +void __unmapVoice(ALSeqPlayer *seqp, ALVoice *voice); +char __voiceNeedsNoteKill(ALSeqPlayer *seqp, ALVoice *voice, ALMicroTime killTime); /* sct 1/5/96 */ + +ALVoiceState *__lookupVoice(ALSeqPlayer *, u8, u8); +ALSound *__lookupSound(ALSeqPlayer *, u8, u8, u8); +ALSound *__lookupSoundQuick(ALSeqPlayer *, u8, u8, u8); + +s16 __vsVol(ALVoiceState *voice, ALSeqPlayer *seqp); +ALMicroTime __vsDelta(ALVoiceState *voice, ALMicroTime t); +ALPan __vsPan(ALVoiceState *voice, ALSeqPlayer *seqp); + +void __initFromBank(ALSeqPlayer *seqp, ALBank *b); +void __initChanState(ALSeqPlayer *seqp); +void __resetPerfChanState(ALSeqPlayer *seqp, s32 chan); +void __setInstChanState(ALSeqPlayer *seqp, ALInstrument *inst, s32 chan); + +void __seqpPrintVoices(ALSeqPlayer *); +void __seqpReleaseVoice(ALSeqPlayer *seqp, ALVoice *voice, + ALMicroTime deltaTime); + +void __seqpStopOsc(ALSeqPlayer *seqp, ALVoiceState *vs); + +void __postNextSeqEvent(ALSeqPlayer *seqp); /* sct 11/7/95 */ + diff --git a/lib/ultralib/src/audio/seqpdelete.c b/lib/ultralib/src/audio/seqpdelete.c new file mode 100644 index 0000000..b4f11fd --- /dev/null +++ b/lib/ultralib/src/audio/seqpdelete.c @@ -0,0 +1,42 @@ +/*==================================================================== + * seqpdelete.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> +#include <assert.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + + +void alSeqpDelete(ALSeqPlayer *seqp) +{ + /* sct 1/4/96 - If the sequence player isn't stopped, then you may end + up with stuck notes. Application should check state before calling + this routine to be sure. */ + +#ifdef _DEBUG + assert(seqp->state == AL_STOPPED); +#endif + + alSynRemovePlayer(seqp->drvr, &seqp->node); +} + diff --git a/lib/ultralib/src/audio/seqpgetchlvol.c b/lib/ultralib/src/audio/seqpgetchlvol.c new file mode 100644 index 0000000..e205651 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetchlvol.c @@ -0,0 +1,27 @@ +/*==================================================================== + * seqpgetchlvol.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alSeqpGetChlVol(ALSeqPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].vol; +} + diff --git a/lib/ultralib/src/audio/seqpgetfxmix.c b/lib/ultralib/src/audio/seqpgetfxmix.c new file mode 100644 index 0000000..5d7ee3f --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetfxmix.c @@ -0,0 +1,27 @@ +/*==================================================================== + * seqpgetfxmix.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alSeqpGetChlFXMix(ALSeqPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].fxmix; +} + diff --git a/lib/ultralib/src/audio/seqpgetpan.c b/lib/ultralib/src/audio/seqpgetpan.c new file mode 100644 index 0000000..23f1067 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetpan.c @@ -0,0 +1,27 @@ +/*==================================================================== + * seqpgetpan.c + * + * Copyright 1995, 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 <libaudio.h> + +ALPan alSeqpGetChlPan(ALSeqPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].pan; +} + diff --git a/lib/ultralib/src/audio/seqpgetpriority.c b/lib/ultralib/src/audio/seqpgetpriority.c new file mode 100644 index 0000000..e6f77a4 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetpriority.c @@ -0,0 +1,26 @@ +/*==================================================================== + * seqpgetpriority.c + * + * Copyright 1995, 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 <libaudio.h> + +u8 alSeqpGetChlPriority(ALSeqPlayer *seqp, u8 chan) +{ + return seqp->chanState[chan].priority; +} diff --git a/lib/ultralib/src/audio/seqpgetprogram.c b/lib/ultralib/src/audio/seqpgetprogram.c new file mode 100644 index 0000000..d421cde --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetprogram.c @@ -0,0 +1,42 @@ +/*==================================================================== + * seqpgetprogram.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +s32 alSeqpGetChlProgram(ALSeqPlayer *seqp, u8 chan) + +{ + s32 i; + ALBank *b = seqp->bank; + ALInstrument *inst; + ALChanState s; + + s = seqp->chanState[chan]; + for (i=0; i<b->instCount; i++){ + inst = b->instArray[i]; + if (inst == s.instrument) + return i; + } + return(-1); + +} + diff --git a/lib/ultralib/src/audio/seqpgetseq.c b/lib/ultralib/src/audio/seqpgetseq.c new file mode 100644 index 0000000..d35ea19 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetseq.c @@ -0,0 +1,29 @@ +/*==================================================================== + * seqpgetseq.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +ALSeq *alSeqpGetSeq(ALSeqPlayer *seqp) +{ + return seqp->target; +} + diff --git a/lib/ultralib/src/audio/seqpgetstate.c b/lib/ultralib/src/audio/seqpgetstate.c new file mode 100644 index 0000000..8d36b49 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetstate.c @@ -0,0 +1,29 @@ +/*==================================================================== + * seqpgetstate.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +s32 alSeqpGetState(ALSeqPlayer *seqp) +{ + return seqp->state; +} + diff --git a/lib/ultralib/src/audio/seqpgettempo.c b/lib/ultralib/src/audio/seqpgettempo.c new file mode 100644 index 0000000..41cd4b4 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgettempo.c @@ -0,0 +1,31 @@ +/*==================================================================== + * seqpgettempo.c + * + * Copyright 1995, 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 <libaudio.h> + +s32 alSeqpGetTempo(ALSeqPlayer *seqp) +{ + /* sct 1/8/96 - If no target sequence has been set, just return zero (instead of crashing). */ + if (seqp->target == NULL) + return 0; + + return seqp->uspt/seqp->target->qnpt; +} + diff --git a/lib/ultralib/src/audio/seqpgetvol.c b/lib/ultralib/src/audio/seqpgetvol.c new file mode 100644 index 0000000..43a3bb8 --- /dev/null +++ b/lib/ultralib/src/audio/seqpgetvol.c @@ -0,0 +1,27 @@ +/*==================================================================== + * seqpgetvol.c + * + * Copyright 1995, 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 <libaudio.h> + +s16 alSeqpGetVol(ALSeqPlayer *seqp) +{ + return seqp->vol; +} + diff --git a/lib/ultralib/src/audio/seqplayer.c b/lib/ultralib/src/audio/seqplayer.c new file mode 100644 index 0000000..3b83257 --- /dev/null +++ b/lib/ultralib/src/audio/seqplayer.c @@ -0,0 +1,1231 @@ +/*==================================================================== + * seqplayer.c + * + * 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. + *====================================================================*/ + +/* + * Notes: + * + * Controller Numbers: + * 1 Modulation + * 7 Volume + * 10 Pan + * 11 Expression + * 64 Sustain + * 121 Reset All Controllers + * 123 All Notes Off + * + * Registered Parameters + * 0 Pitch Bend Sensitivity + * 1 Fine Tuning + * 2 Coarse Tuning + */ + +#include <libaudio.h> +#include <os_internal.h> +#include <ultraerror.h> +#include <assert.h> +#include "seqp.h" +#include "seq.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + + +static ALMicroTime __seqpVoiceHandler(void *node); +static void __handleMIDIMsg(ALSeqPlayer *seqp, ALEvent *event); +static void __handleMetaMsg(ALSeqPlayer *seqp, ALEvent *event); +static void __handleNextSeqEvent(ALSeqPlayer *seqp); +static void __setUsptFromTempo(ALSeqPlayer *seqp, f32 tempo); /* sct 1/8/96 */ + +/* + * Sequence Player public functions + */ +void alSeqpNew(ALSeqPlayer *seqp, ALSeqpConfig *c) +{ + s32 i; + ALEventListItem *items; + ALVoiceState *vs; + ALVoiceState *voices; + ALHeap *hp = c->heap; + + /* + * initialize member variables + */ + seqp->bank = 0; + seqp->target = NULL; + seqp->drvr = &alGlobals->drvr; + seqp->chanMask = 0xff; + 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->loopStart = 0; + seqp->loopEnd = 0; + seqp->loopCount = 0; /* -1 = loop forever, 0 = no loop */ + + seqp->nextEvent.type = AL_SEQP_API_EVT; /* start the voice handler "spinning" */ + + /* + * init the channel state + */ + seqp->maxChannels = c->maxChannels; + seqp->chanState = alHeapAlloc(hp, c->maxChannels, sizeof(ALChanState) ); + __initChanState(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 = __seqpVoiceHandler; + seqp->node.clientData = seqp; + alSynAddPlayer(&alGlobals->drvr, &seqp->node); +} + +/************************************************************* + * private routines or driver callback routines + *************************************************************/ +ALMicroTime __seqpVoiceHandler(void *node) +{ + ALSeqPlayer *seqp = (ALSeqPlayer *) node; + ALEvent evt; + ALVoice *voice; + ALMicroTime delta; + ALVoiceState *vs; + void *oscState; + f32 oscValue; + u8 chan; + + do { + + switch (seqp->nextEvent.type) { + + case (AL_SEQ_REF_EVT): + __handleNextSeqEvent(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; + alSynStopVoice(seqp->drvr, voice); + alSynFreeVoice(seqp->drvr, voice); + vs = (ALVoiceState *)voice->clientPrivate; + if(vs->flags) + __seqpStopOsc((ALSeqPlayer*)seqp,vs); + __unmapVoice(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->envGain = seqp->nextEvent.msg.vol.vol; + vs->envEndTime = seqp->curTime + delta; + alSynSetVol(seqp->drvr, voice, __vsVol(vs, 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; + alSynSetVol(seqp->drvr, &vs->voice, __vsVol(vs,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; + alSynSetPitch(seqp->drvr, &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): + __handleMIDIMsg(seqp, &seqp->nextEvent); + break; + + case (AL_SEQP_META_EVT): + __handleMetaMsg(seqp, &seqp->nextEvent); + break; + + case (AL_SEQP_PLAY_EVT): + if (seqp->state != AL_PLAYING) + { + seqp->state = AL_PLAYING; + __postNextSeqEvent(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) + { + alSynStopVoice(seqp->drvr, &vs->voice); + alSynFreeVoice(seqp->drvr, &vs->voice); + if(vs->flags) + __seqpStopOsc((ALSeqPlayer*)seqp,vs); + __unmapVoice((ALSeqPlayer*)seqp, &vs->voice); + } + + seqp->curTime = 0; + 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. 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_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 (seqp, &vs->voice, KILL_TIME)) + __seqpReleaseVoice(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_VOL_EVT): + seqp->vol = seqp->nextEvent.msg.spvol.vol; + for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) { + alSynSetVol(seqp->drvr, &vs->voice, __vsVol(vs, seqp), + __vsDelta(vs, seqp->curTime)); + } + break; + + case (AL_SEQP_LOOP_EVT): + seqp->loopStart = seqp->nextEvent.msg.loop.start; + seqp->loopEnd = seqp->nextEvent.msg.loop.end; + seqp->loopCount = seqp->nextEvent.msg.loop.count; + 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): + +#ifdef _DEBUG + assert(seqp->state != AL_PLAYING); /* Must be done playing to change sequences. */ +#endif + + seqp->target = seqp->nextEvent.msg.spseq.seq; + __setUsptFromTempo (seqp, 500000.0); + if (seqp->bank) + __initFromBank(seqp, seqp->bank); + break; + + case (AL_SEQP_BANK_EVT): + +#ifdef _DEBUG + assert(seqp->state == AL_STOPPED); /* Must be fully stopped to change banks. */ +#endif + + seqp->bank = seqp->nextEvent.msg.spbank.bank; + __initFromBank(seqp, seqp->bank); + break; + + /* sct 11/6/95 - these events should now be handled by __handleNextSeqEvent */ + case (AL_SEQ_END_EVT): + case (AL_TEMPO_EVT): + case (AL_SEQ_MIDI_EVT): + +#ifdef _DEBUG + assert(FALSE); +#endif + + 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; /* Update the player's current time. */ + return seqp->nextDelta; +} + + +/* + Calculates the delta time in ticks until the next sequence + event taking into account loop points, and posts a + sequence reference event with the time in usecs. + + Does nothing if the sequence player is not playing or there + is no target sequence. + + sct 11/7/95 +*/ +void __postNextSeqEvent(ALSeqPlayer *seqp) +{ + ALEvent evt; + s32 deltaTicks; + ALSeq *seq = seqp->target; + + /* sct 1/5/96 - Do nothing if we're not playing or don't have a target sequence. */ + if ((seqp->state != AL_PLAYING) || (seq == 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 (!__alSeqNextDelta(seq, &deltaTicks)) + return; + + /* Handle loops. */ + if (seqp->loopCount) + { + /* Assume that the loop end falls on a MIDI event. Delta time + will be correct even if we loop */ + if (alSeqGetTicks(seq) + deltaTicks >= seqp->loopEnd->curTicks) + { + alSeqSetLoc(seq, seqp->loopStart); + + if (seqp->loopCount != -1) + seqp->loopCount--; + } + } + + 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 +__handleNextSeqEvent(ALSeqPlayer *seqp) +{ + ALEvent evt; + + /* sct 1/5/96 - Do nothing if we don't have a target sequence. */ + if (seqp->target == NULL) + return; + + alSeqNextEvent(seqp->target, &evt); + + switch (evt.type) + { + case AL_SEQ_MIDI_EVT: + __handleMIDIMsg(seqp, &evt); + __postNextSeqEvent(seqp); + break; + + case AL_TEMPO_EVT: + __handleMetaMsg(seqp, &evt); + __postNextSeqEvent(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; + + default: + +#ifdef _DEBUG + assert(FALSE); /* Sequence event type not supported. */ +#endif + + break; + } +} + + +void __handleMIDIMsg(ALSeqPlayer *seqp, ALEvent *event) +{ + ALVoice *voice; + ALVoiceState *vs; + s32 status; + u8 chan; + u8 key; + u8 vel; + u8 byte1; + u8 byte2; + ALMIDIEvent *midi = &event->msg.midi; + s16 vol; + ALEvent evt; + ALMicroTime deltaTime; + ALVoiceState *vstate; + ALPan pan; + ALFxRef fxref; + +#ifdef _DEBUG + /* sct 12/15/95 - Fixed assert to also allow seqp midi event types. */ + assert(event->type == AL_SEQ_MIDI_EVT || event->type == AL_SEQP_MIDI_EVT); +#endif + + status = midi->status & AL_MIDI_StatusMask; + chan = midi->status & AL_MIDI_ChannelMask; + byte1 = key = midi->byte1; + byte2 = vel = midi->byte2; + + 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(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(seqp, key, vel, chan); + ALFlagFailIf(!vstate, seqp->debugFlags & NO_VOICE_ERR_MASK, + ERR_ALSEQP_NO_VOICE ); + + voice = &vstate->voice; + + alSynAllocVoice(seqp->drvr, 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) /* if deltaTime = zero, 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 */ + } + } + } + /* will default if not changed by initOsc */ + vstate->tremelo = (u8)oscValue; + + 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) /* if deltaTime = zero,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 */ + } + } + } + /* will default if not changed by initOsc */ + vstate->vibrato = oscValue; + + /* + * calculate the note on parameters + */ + pitch = vstate->pitch * seqp->chanState[chan].pitchBend * + vstate->vibrato; + fxmix = seqp->chanState[chan].fxmix; + pan = __vsPan(vstate, seqp); + vol = __vsVol(vstate, seqp); + deltaTime = sound->envelope->attackTime; + + alSynStartVoiceParams(seqp->drvr, 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; + deltaTime = sound->envelope->attackTime; + + alEvtqPostEvent(&seqp->evtq, &evt, deltaTime); + + break; + } + + /* + * NOTE: intentional fall-through for note on with zero + * velocity + */ + + case (AL_MIDI_NoteOff): + vstate = __lookupVoice(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(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(seqp, key, chan); + ALFailIf(!vstate, ERR_ALSEQP_POLY_VOICE ); + + vstate->velocity = byte2; + alSynSetVol(seqp->drvr, &vstate->voice, __vsVol(vstate, 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; + alSynSetVol(seqp->drvr, &vs->voice, __vsVol(vs, 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, seqp); + alSynSetPan(seqp->drvr, &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, seqp); + alSynSetVol(seqp->drvr, &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(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) { + alSynSetFXMix(seqp->drvr, &vs->voice, byte2); + } + } + break; + + case (AL_MIDI_FX_CTRL_0): + case (AL_MIDI_FX_CTRL_1): + case (AL_MIDI_FX_CTRL_2): + case (AL_MIDI_FX_CTRL_3): + case (AL_MIDI_FX_CTRL_4): + case (AL_MIDI_FX_CTRL_5): + case (AL_MIDI_FX_CTRL_6): + case (AL_MIDI_FX_CTRL_7): +#if 0 /* fx control not implemented */ + fxref = alSynGetFXRef(seqp->drvr, 0, 0); + if (fxref) + alSynSetFXParam(seqp->drvr, fxref, (s16)byte1, (void *)byte2); + break; +#endif + case (AL_MIDI_FX3_CTRL): + default: + break; + + } + break; + + case (AL_MIDI_ProgramChange): + /* sct 1/16/96 - We must have a valid bank in order to process the program change. */ + +#ifdef _DEBUG + assert(seqp->bank != NULL); +#endif + + if (key < seqp->bank->instCount) { + ALInstrument *inst = seqp->bank->instArray[key]; + __setInstChanState(seqp, inst, chan); /* sct 11/6/95 */ + } +#ifdef _DEBUG + else + __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) { + alSynSetPitch(seqp->drvr, &vs->voice, + vs->pitch * bendRatio * vs->vibrato); + } + } + } + break; + + default: +#ifdef _DEBUG + __osError(ERR_ALSEQPUNKNOWNMIDI, 1, status); +#endif + break; + } +} + +void __handleMetaMsg(ALSeqPlayer *seqp, ALEvent *event) +{ + ALTempoEvent *tevt = &event->msg.tempo; + ALEvent evt; + s32 tempo; + + if (event->msg.tempo.status == AL_MIDI_Meta) + { + if (event->msg.tempo.type == AL_MIDI_META_TEMPO) + { + tempo = + (tevt->byte1 << 16) | + (tevt->byte2 << 8) | + (tevt->byte3 << 0); + __setUsptFromTempo (seqp, (f32)tempo); /* sct 1/8/96 */ + } + } +} + +ALVoiceState *__mapVoice(ALSeqPlayer *seqp, u8 key, u8 vel, u8 channel) +{ + ALVoiceState *vs = seqp->vFreeList; + + if (vs) { + + seqp->vFreeList = vs->next; + + vs->next = 0; + + if (!seqp->vAllocHead) + seqp->vAllocHead = vs; + else + seqp->vAllocTail->next = vs; + + seqp->vAllocTail = vs; + + vs->channel = channel; + vs->key = key; + vs->velocity = vel; + vs->voice.clientPrivate = vs; + } + + return vs; +} + +void __unmapVoice(ALSeqPlayer *seqp, ALVoice *voice) +{ + ALVoiceState *prev = 0; + ALVoiceState *vs; + + /* + * we could use doubly linked lists here and save some code and + * execution time, but time spent here in negligible, so it won't + * make much difference. + */ + for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) { + if (&vs->voice == voice) { + + if (prev) + prev->next = vs->next; + else + seqp->vAllocHead = vs->next; + + if (vs == seqp->vAllocTail) { + seqp->vAllocTail = prev; + } + + vs->next = seqp->vFreeList; + seqp->vFreeList = vs; + return; + + } + prev = vs; + } +#ifdef _DEBUG + __osError(ERR_ALSEQPUNMAP, 1, voice); +#endif +} + +ALVoiceState *__lookupVoice(ALSeqPlayer *seqp, u8 key, u8 channel) +{ + ALVoiceState *vs; + + for (vs = seqp->vAllocHead; vs != 0; vs = vs->next) { + if ((vs->key == key) && (vs->channel == channel) && + (vs->phase != AL_PHASE_RELEASE) && (vs->phase != AL_PHASE_SUSTREL)) + return vs; + } + + return 0; +} + +#if 0 +ALSound *__lookupSound(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan) +{ + s32 i; + ALInstrument *inst = seqp->chanState[chan].instrument; + ALSound *snd = 0; + + for (i = 0; i < inst->soundCount; i++) { + ALSound *sound = inst->soundArray[i]; + ALKeyMap *keymap = sound->keyMap; + + if ((key >= keymap->keyMin) && (key <= keymap->keyMax) && + (vel >= keymap->velocityMin) && (vel <= keymap->velocityMax)) { + snd = sound; + break; + } + } + return snd; +} +#endif + +ALSound *__lookupSoundQuick(ALSeqPlayer *seqp, u8 key, u8 vel, u8 chan) +{ + ALInstrument *inst = seqp->chanState[chan].instrument; + s32 l = 1; + s32 r = inst->soundCount; + s32 i; + ALKeyMap *keymap; + +#ifdef _DEBUG + assert(inst != NULL); /* sct 10/31/95 - If inst is NULL, then the seqp probably wasn't setup correctly. */ +#endif + + while (r >= l) { + i = (l+r)/2; + + keymap = inst->soundArray[i-1]->keyMap; + + if ((key >= keymap->keyMin) && (key <= keymap->keyMax) && + (vel >= keymap->velocityMin) && (vel <= keymap->velocityMax)) { + return inst->soundArray[i-1]; + } else if ((key < keymap->keyMin) || + ((vel < keymap->velocityMin) && (key <= keymap->keyMax))) { + r = i - 1; + } else { + l = i + 1; + } + } + + return 0; +} + + +/* + * __vsVol calculates the target volume for the voice based on the + * note on velocity, envelope, sampleVolume and controller. + */ +s16 __vsVol(ALVoiceState *vs, ALSeqPlayer *seqp) +{ + + u32 t1,t2; + + t1 = (vs->tremelo*vs->velocity*vs->envGain) >> 6; + t2 = (vs->sound->sampleVolume*seqp->vol* + seqp->chanState[vs->channel].vol) >> 14; + + t1 *= t2; + t1 >>= 15; + + return( (s16)t1 ); + +} + +ALMicroTime __vsDelta(ALVoiceState *vs, ALMicroTime t) +{ + /* + * If we are interrupting a previously set envelope segment, we + * need to recalculate the segment end time given the current + * time. Note: this routine assumes that the voice is currently + * playing. + */ + + s32 delta = vs->envEndTime - t; + + if (delta >= 0) { + return delta; + } else { + return AL_GAIN_CHANGE_TIME; + } +} + + +ALPan __vsPan(ALVoiceState *vs, ALSeqPlayer *seqp) +{ + s32 tmp; + + tmp = seqp->chanState[vs->channel].pan - AL_PAN_CENTER + + vs->sound->samplePan; + tmp = MAX(tmp, AL_PAN_LEFT); + tmp = MIN(tmp, AL_PAN_RIGHT); + + return (ALPan) tmp; +} + +#ifdef IMPLEMENTED + +s32 seqpGetVoices(SEQP *seqp); +s32 seqpSetVoices(SEQP *seqp, s32 numvoices); + +u16 seqpGetChannelMask(SEQP *seqp); +s32 seqpSetChannelMask(SEQP *seqp, u16 bitmask); + +#endif + +void __seqpReleaseVoice(ALSeqPlayer *seqp, ALVoice *voice, + ALMicroTime deltaTime) +{ + ALEvent evt; + ALVoiceState *vs = (ALVoiceState *)voice->clientPrivate; + + /* + * if in attack phase, remove all pending volume + * events for this voice from the queue + */ + + if (vs->envPhase == AL_PHASE_ATTACK) { + ALLink *thisNode; + ALLink *nextNode; + ALEventListItem *thisItem, *nextItem; + + thisNode = seqp->evtq.allocList.next; + while( thisNode != 0 ) { + nextNode = thisNode->next; + thisItem = (ALEventListItem *)thisNode; + nextItem = (ALEventListItem *)nextNode; + if (thisItem->evt.type == AL_SEQP_ENV_EVT) { + if(thisItem->evt.msg.vol.voice == voice) { + if( nextItem ) + nextItem->delta += thisItem->delta; + alUnlink(thisNode); + alLink(thisNode, &seqp->evtq.freeList); + } + } + thisNode = nextNode; + } + } + + vs->velocity = 0; + vs->envPhase = AL_PHASE_RELEASE; + vs->envGain = 0; + vs->envEndTime = seqp->curTime + deltaTime; + + alSynSetPriority(seqp->drvr, voice, 0); /* make candidate for stealing */ + alSynSetVol(seqp->drvr, voice, 0, deltaTime); + evt.type = AL_NOTE_END_EVT; + evt.msg.note.voice = voice; + + alEvtqPostEvent(&seqp->evtq, &evt, deltaTime); +} + + + +/* + This special purpose routine is called only when processing + a stopping event in order to properly kill all active voices. + + The routine searches through the seqp's event queue for an + AL_NOTE_END_EVT for the given voice. If the event's execution + time is greater than kill time, it removes the event from the + event queue and returns true that it needs to kill the voice. + Otherwise, if the event's time is less than the kill time, it + returns false that the voice needs to be killed. + + sct 1/3/96 +*/ + +#define VOICENEEDSNOTEKILL_DEBUG _DEBUG_INTERNAL&&0 /* For debugging voiceNeedsNoteKill routine. */ + +char __voiceNeedsNoteKill (ALSeqPlayer *seqp, ALVoice *voice, ALMicroTime killTime) +{ + ALLink *thisNode; + ALLink *nextNode; + ALEventListItem *thisItem; + ALMicroTime itemTime = 0; + char needsNoteKill = TRUE; + +#if VOICENEEDSNOTEKILL_DEBUG + alEvtqPrintAllocEvts (&seqp->evtq); +#endif + + thisNode = seqp->evtq.allocList.next; + while (thisNode != 0) + { + nextNode = thisNode->next; + thisItem = (ALEventListItem *)thisNode; + itemTime += thisItem->delta; + + if (thisItem->evt.type == AL_NOTE_END_EVT) + { + if (thisItem->evt.msg.note.voice == voice) + { + if (itemTime > killTime) + { + if ((ALEventListItem *)nextNode) + ((ALEventListItem *)nextNode)->delta += thisItem->delta; + alUnlink(thisNode); + alLink(thisNode, &seqp->evtq.freeList); + } + else + needsNoteKill = FALSE; + break; + } + } + thisNode = nextNode; + } + +#if VOICENEEDSNOTEKILL_DEBUG + if (thisNode) + osSyncPrintf("vox 0x%0x: end time %d kill time %d\n\n", voice, itemTime, killTime); + else + osSyncPrintf("vox 0x%0x: not found\n\n", voice); + + alEvtqPrintAllocEvts (&seqp->evtq); +#endif + + return needsNoteKill; +} + + + + +void __initFromBank(ALSeqPlayer *seqp, ALBank *b) +{ + /* + * init the chanState with the default instrument + */ + s32 i; + ALInstrument *inst = 0; + + /* set to the first available instrument. */ + for(i = 0; !inst ; i++) + inst = b->instArray[i]; + + /* sct 11/6/95 - Setup the channel state for the given instrument. */ + /* There is some wasted effort here since both calls the same state vars */ + /* but it's safer. */ + for (i = 0; i < seqp->maxChannels; i++) { + __resetPerfChanState(seqp, i); + __setInstChanState(seqp, inst, i); + } + + if (b->percussion) { + __resetPerfChanState(seqp, i); + __setInstChanState(seqp, b->percussion, 9); + } +} + + +/* + sct 11/6/95 - Call this whenever a new instrument gets assigned to a channel + such as when changing banks or in response to a MIDI program change event. + Currently also gets called when changing sequences. +*/ +void __setInstChanState(ALSeqPlayer *seqp, ALInstrument *inst, s32 chan) +{ + seqp->chanState[chan].instrument = inst; + seqp->chanState[chan].pan = inst->pan; + seqp->chanState[chan].vol = inst->volume; + seqp->chanState[chan].priority = inst->priority; + seqp->chanState[chan].bendRange = inst->bendRange; +} + + +/* + sct 11/6/95 -- Call this whenever a new sequence is to be played or when + initializing a sequence player. +*/ +void __resetPerfChanState(ALSeqPlayer *seqp, s32 chan) +{ + seqp->chanState[chan].fxId = AL_FX_NONE; + seqp->chanState[chan].fxmix = AL_DEFAULT_FXMIX; + seqp->chanState[chan].pan = AL_PAN_CENTER; + seqp->chanState[chan].vol = AL_VOL_FULL; + seqp->chanState[chan].priority = AL_DEFAULT_PRIORITY; + seqp->chanState[chan].sustain = 0; + seqp->chanState[chan].bendRange = 200; + seqp->chanState[chan].pitchBend = 1.0f; +} + + +/* + sct 11/6/95 - Called only when creating a new sequence player. +*/ +void __initChanState(ALSeqPlayer *seqp) +{ + int i; + + for (i = 0; i < seqp->maxChannels; i++) + { + seqp->chanState[i].instrument = 0; + __resetPerfChanState (seqp, i); + } +} + + +void __seqpStopOsc(ALSeqPlayer *seqp, ALVoiceState *vs) +{ + ALEventListItem *thisNode,*nextNode; + s16 evtType; + + thisNode = (ALEventListItem*)seqp->evtq.allocList.next; + while(thisNode) + { + nextNode = (ALEventListItem*)thisNode->node.next; + evtType = thisNode->evt.type; + if(evtType == AL_TREM_OSC_EVT || evtType == AL_VIB_OSC_EVT) + { + if(thisNode->evt.msg.osc.vs == vs) + { + (*seqp->stopOsc)(thisNode->evt.msg.osc.oscState); + alUnlink((ALLink*)thisNode); + if(nextNode) + nextNode->delta += thisNode->delta; + alLink((ALLink*)thisNode, &seqp->evtq.freeList); + if(evtType == AL_TREM_OSC_EVT) + vs->flags = vs->flags & 0xFE; + else /* must be a AL_VIB_OSC_EVT */ + vs->flags = vs->flags & 0xFD; + if(!vs->flags) + return; /* there should be no more events */ + } + } + + thisNode = nextNode; + } +} + + + +/* + 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. +*/ +static void __setUsptFromTempo (ALSeqPlayer *seqp, f32 tempo) +{ + if (seqp->target) + seqp->uspt = (s32)((f32)tempo * seqp->target->qnpt); + else + seqp->uspt = 488; /* This is the initial value set by alSeqpNew. */ +} diff --git a/lib/ultralib/src/audio/seqploop.c b/lib/ultralib/src/audio/seqploop.c new file mode 100644 index 0000000..9bbaf5f --- /dev/null +++ b/lib/ultralib/src/audio/seqploop.c @@ -0,0 +1,35 @@ +/*==================================================================== + * seqploop.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpLoop(ALSeqPlayer *seqp, ALSeqMarker *start, ALSeqMarker *end, + s32 count) +{ + ALEvent evt; + + evt.type = AL_SEQP_LOOP_EVT; + evt.msg.loop.start = start; + evt.msg.loop.end = end; + evt.msg.loop.count = count; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpplay.c b/lib/ultralib/src/audio/seqpplay.c new file mode 100644 index 0000000..8e65504 --- /dev/null +++ b/lib/ultralib/src/audio/seqpplay.c @@ -0,0 +1,48 @@ +/*==================================================================== + * seqpplay.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> +#include "seqp.h" + +void alSeqpPlay(ALSeqPlayer *seqp) +{ + ALEvent evt; + + evt.type = AL_SEQP_PLAY_EVT; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + + + + + + + + + + + + + + + diff --git a/lib/ultralib/src/audio/seqpsendmidi.c b/lib/ultralib/src/audio/seqpsendmidi.c new file mode 100644 index 0000000..56a9510 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsendmidi.c @@ -0,0 +1,40 @@ +/*==================================================================== + * seqpsendmidi.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSendMidi(ALSeqPlayer *seqp, s32 ticks, u8 status, u8 byte1, + u8 byte2) +{ + ALEvent evt; + ALMicroTime deltaTime; + + evt.type = AL_SEQP_MIDI_EVT; + evt.msg.midi.ticks = 0; + evt.msg.midi.status = status; + evt.msg.midi.byte1 = byte1; + evt.msg.midi.byte2 = byte2; + evt.msg.midi.duration = 0; + + deltaTime = ticks*seqp->uspt; + + alEvtqPostEvent(&seqp->evtq, &evt, deltaTime); +} + diff --git a/lib/ultralib/src/audio/seqpsetbank.c b/lib/ultralib/src/audio/seqpsetbank.c new file mode 100644 index 0000000..1c00e8b --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetbank.c @@ -0,0 +1,32 @@ +/*==================================================================== + * seqpsetbank.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetBank(ALSeqPlayer *seqp, ALBank *b) +{ + ALEvent evt; + + evt.type = AL_SEQP_BANK_EVT; + evt.msg.spbank.bank = b; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsetchlvol.c b/lib/ultralib/src/audio/seqpsetchlvol.c new file mode 100644 index 0000000..9b48803 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetchlvol.c @@ -0,0 +1,35 @@ +/*==================================================================== + * seqpsetchlvol.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetChlVol(ALSeqPlayer *seqp, u8 chan, u8 vol) +{ + 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 = AL_MIDI_VOLUME_CTRL; + evt.msg.midi.byte2 = vol; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsetfxmix.c b/lib/ultralib/src/audio/seqpsetfxmix.c new file mode 100644 index 0000000..9397963 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetfxmix.c @@ -0,0 +1,35 @@ +/*==================================================================== + * seqpsetfxmix.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetChlFXMix(ALSeqPlayer *seqp, u8 chan, u8 fxmix) +{ + 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 = AL_MIDI_FX1_CTRL; + evt.msg.midi.byte2 = fxmix; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsetpan.c b/lib/ultralib/src/audio/seqpsetpan.c new file mode 100644 index 0000000..85d07d9 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetpan.c @@ -0,0 +1,35 @@ +/*==================================================================== + * seqpsetpan.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetChlPan(ALSeqPlayer *seqp, u8 chan, ALPan pan) +{ + 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 = AL_MIDI_PAN_CTRL; + evt.msg.midi.byte2 = pan; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsetpriority.c b/lib/ultralib/src/audio/seqpsetpriority.c new file mode 100644 index 0000000..0910726 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetpriority.c @@ -0,0 +1,32 @@ +/*==================================================================== + * seqpsetpriority.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetChlPriority(ALSeqPlayer *seqp, u8 chan, u8 priority) +{ + ALEvent evt; + + evt.type = AL_SEQP_PRIORITY_EVT; + evt.msg.sppriority.chan = chan; + evt.msg.sppriority.priority = priority; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} diff --git a/lib/ultralib/src/audio/seqpsetprogram.c b/lib/ultralib/src/audio/seqpsetprogram.c new file mode 100644 index 0000000..dfd6d94 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetprogram.c @@ -0,0 +1,36 @@ +/*==================================================================== + * seqpsetprogram.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetChlProgram(ALSeqPlayer *seqp, u8 chan, u8 prog) + +{ + ALEvent evt; + + evt.type = AL_SEQP_MIDI_EVT; + evt.msg.midi.ticks = 0; + evt.msg.midi.status = AL_MIDI_ProgramChange | chan; + evt.msg.midi.byte1 = prog; + evt.msg.midi.byte2 = 0; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsetseq.c b/lib/ultralib/src/audio/seqpsetseq.c new file mode 100644 index 0000000..3fe8175 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetseq.c @@ -0,0 +1,34 @@ +/*==================================================================== + * seqpsetseq.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetSeq(ALSeqPlayer *seqp, ALSeq *seq) +{ + ALEvent evt; + + evt.type = AL_SEQP_SEQ_EVT; + evt.msg.spseq.seq = seq; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpsettempo.c b/lib/ultralib/src/audio/seqpsettempo.c new file mode 100644 index 0000000..592320a --- /dev/null +++ b/lib/ultralib/src/audio/seqpsettempo.c @@ -0,0 +1,36 @@ +/*==================================================================== + * seqpsettempo.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetTempo(ALSeqPlayer *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); +} + diff --git a/lib/ultralib/src/audio/seqpsetvol.c b/lib/ultralib/src/audio/seqpsetvol.c new file mode 100644 index 0000000..b698a40 --- /dev/null +++ b/lib/ultralib/src/audio/seqpsetvol.c @@ -0,0 +1,32 @@ +/*==================================================================== + * seqpsetvol.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpSetVol(ALSeqPlayer *seqp, s16 vol) +{ + ALEvent evt; + + evt.type = AL_SEQP_VOL_EVT; + evt.msg.spvol.vol = vol; + + alEvtqPostEvent(&seqp->evtq, &evt, 0); +} + diff --git a/lib/ultralib/src/audio/seqpstop.c b/lib/ultralib/src/audio/seqpstop.c new file mode 100644 index 0000000..abec781 --- /dev/null +++ b/lib/ultralib/src/audio/seqpstop.c @@ -0,0 +1,33 @@ +/*==================================================================== + * seqpstop.c + * + * Synopsis: + * + * Copyright 1995, 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 <libaudio.h> + +void alSeqpStop(ALSeqPlayer *seqp) +{ + ALEvent evt; + + evt.type = AL_SEQP_STOPPING_EVT; + alEvtqPostEvent(&seqp->evtq, &evt, 0); + +} + diff --git a/lib/ultralib/src/audio/sl.c b/lib/ultralib/src/audio/sl.c new file mode 100644 index 0000000..d184972 --- /dev/null +++ b/lib/ultralib/src/audio/sl.c @@ -0,0 +1,65 @@ +/*==================================================================== + * sl.c + * + * Synopsis: + * Sound library global routines + * + * 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 <libaudio.h> + +ALGlobals *alGlobals=0; + +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; + } +} + +/* might want to make these macros */ +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; +} + + + + + diff --git a/lib/ultralib/src/audio/sndp.h b/lib/ultralib/src/audio/sndp.h new file mode 100644 index 0000000..17d7015 --- /dev/null +++ b/lib/ultralib/src/audio/sndp.h @@ -0,0 +1,102 @@ +/*==================================================================== + * sndp.h + * + * Synopsis: + * + * Copyright 1995, 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. + *====================================================================*/ + + +#ifndef __SNDP__ +#define __SNDP__ + +#include <libaudio.h> + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define MIN_RATIO 0.0001 + +typedef enum { + AL_SNDP_PLAY_EVT, + AL_SNDP_STOP_EVT, + AL_SNDP_PAN_EVT, + AL_SNDP_VOL_EVT, + AL_SNDP_PITCH_EVT, + AL_SNDP_API_EVT, + AL_SNDP_DECAY_EVT, + AL_SNDP_END_EVT, + AL_SNDP_FX_EVT +} ALSndpMsgType; + +typedef struct { + ALVoice voice; + ALSound *sound; /* sound referenced here */ + s16 priority; + f32 pitch; /* current playback pitch */ + s32 state; /* play state for this sound */ + s16 vol; /* volume - combined with volume from bank */ + ALPan pan; /* pan - 0 = left, 127 = right */ + u8 fxMix; /* wet/dry mix - 0 = dry, 127 = wet */ +} ALSoundState; + +typedef union { + + ALEvent msg; + + struct { + s16 type; + ALSoundState *state; + } common; + + struct { + s16 type; + ALSoundState *state; + s16 vol; + } vol; + + struct { + s16 type; + ALSoundState *state; + f32 pitch; + } pitch; + + struct { + s16 type; + ALSoundState *state; + ALPan pan; + } pan; + + struct { + s16 type; + ALSoundState *state; + u8 mix; + } fx; + +} ALSndpEvent; + +static ALMicroTime _sndpVoiceHandler(void *node); +static void _handleEvent(ALSndPlayer *sndp, ALSndpEvent *event); +static void _removeEvents(ALEventQueue *evtq, ALSoundState *state); +static s32 _DivS32ByF32 (s32 i, f32 f); + +#endif diff --git a/lib/ultralib/src/audio/sndpallocate.c b/lib/ultralib/src/audio/sndpallocate.c new file mode 100644 index 0000000..0629ac7 --- /dev/null +++ b/lib/ultralib/src/audio/sndpallocate.c @@ -0,0 +1,43 @@ +/*==================================================================== + * sndpallocate.c + * + * Copyright 1995, 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 "sndp.h" + +ALSndId alSndpAllocate(ALSndPlayer *sndp, ALSound *sound) +{ + ALSndId i; + ALSoundState *sState = sndp->sndState; + + for (i = 0; i < sndp->maxSounds; i++) { + if (!sState[i].sound) { + sState[i].sound = sound; + sState[i].priority = AL_DEFAULT_PRIORITY; + sState[i].state = AL_STOPPED; + sState[i].pitch = 1.0; + sState[i].pan = AL_PAN_CENTER; + sState[i].fxMix = AL_DEFAULT_FXMIX; + sState[i].vol = 32767*sound->sampleVolume/AL_VOL_FULL; + return i; + } + } + + return -1; +} + diff --git a/lib/ultralib/src/audio/sndpdeallocate.c b/lib/ultralib/src/audio/sndpdeallocate.c new file mode 100644 index 0000000..7c18b56 --- /dev/null +++ b/lib/ultralib/src/audio/sndpdeallocate.c @@ -0,0 +1,35 @@ +/*==================================================================== + * sndpdeallocate.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpDeallocate(ALSndPlayer *sndp, ALSndId id) +{ + ALSoundState *sState = sndp->sndState; + + ALFailIf((sState + id)->state != AL_STOPPED, ERR_ALSNDPDEALLOCATE); + + sState[id].sound = 0; + if (sndp->target == id) /* if we are deleting the target sound */ + sndp->target = -1; +} + diff --git a/lib/ultralib/src/audio/sndpdelete.c b/lib/ultralib/src/audio/sndpdelete.c new file mode 100644 index 0000000..5cfb4f7 --- /dev/null +++ b/lib/ultralib/src/audio/sndpdelete.c @@ -0,0 +1,44 @@ +/*==================================================================== + * sndpdelete.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpDelete(ALSndPlayer *sndp) +{ + /* + * Remove client from synthesizer. Note application is responsible + * for making sure all sounds have been stopped beforehand. + */ +#ifdef _DEBUG + { + int i, notStopped = 0; + ALSoundState *sState = sndp->sndState; + + for (i=0; i<sndp->maxSounds; i++) + if ((sState + i)->state != AL_STOPPED) + notStopped = 1; + ALFailIf(notStopped, ERR_ALSNDPDELETE); + } +#endif + alSynRemovePlayer(&alGlobals->drvr, &sndp->node); +} + diff --git a/lib/ultralib/src/audio/sndpgetsound.c b/lib/ultralib/src/audio/sndpgetsound.c new file mode 100644 index 0000000..9088982 --- /dev/null +++ b/lib/ultralib/src/audio/sndpgetsound.c @@ -0,0 +1,27 @@ +/*==================================================================== + * sndpgetsound.c + * + * Copyright 1995, 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 "sndp.h" + +ALSndId alSndpGetSound(ALSndPlayer *sndp) +{ + return (ALSndId) sndp->target; +} + diff --git a/lib/ultralib/src/audio/sndpgetstate.c b/lib/ultralib/src/audio/sndpgetstate.c new file mode 100644 index 0000000..882b4a3 --- /dev/null +++ b/lib/ultralib/src/audio/sndpgetstate.c @@ -0,0 +1,29 @@ +/*==================================================================== + * sndpgetstate.c + * + * Copyright 1995, 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 "sndp.h" + +s32 alSndpGetState(ALSndPlayer *sndp) +{ + ALSoundState *sState = sndp->sndState; + + return (sState + sndp->target)->state; +} + diff --git a/lib/ultralib/src/audio/sndplayer.c b/lib/ultralib/src/audio/sndplayer.c new file mode 100644 index 0000000..391e6ac --- /dev/null +++ b/lib/ultralib/src/audio/sndplayer.c @@ -0,0 +1,300 @@ +/*==================================================================== + * Sndplayer.c + * + * 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> +#include <assert.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void alSndpNew(ALSndPlayer *sndp, ALSndpConfig *c) +{ + u8 *ptr; + ALEvent evt; + ALSoundState *sState; + u32 i; + + /* + * Init member variables + */ + sndp->maxSounds = c->maxSounds; + sndp->target = -1; + sndp->frameTime = AL_USEC_PER_FRAME; /* time between API events */ + sState = (ALSoundState*)alHeapAlloc(c->heap, 1, + c->maxSounds * sizeof(ALSoundState)); + sndp->sndState = sState; + + for(i = 0; i < c->maxSounds; i++) + sState[i].sound = 0; + + /* + * init the event queue + */ + ptr = alHeapAlloc(c->heap, 1, c->maxEvents * sizeof(ALEventListItem)); + alEvtqNew(&sndp->evtq, (ALEventListItem *)ptr, c->maxEvents); + + /* + * add ourselves to the driver + */ + sndp->drvr = &alGlobals->drvr; + sndp->node.next = NULL; + sndp->node.handler = _sndpVoiceHandler; + sndp->node.clientData = sndp; + alSynAddPlayer(sndp->drvr, &sndp->node); + + /* + * Start responding to API events + */ + evt.type = AL_SNDP_API_EVT; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, sndp->frameTime); + sndp->nextDelta = alEvtqNextEvent(&sndp->evtq, &sndp->nextEvent); + +} + +/************************************************************* + * Sound Player private routines + *************************************************************/ +ALMicroTime _sndpVoiceHandler(void *node) +{ + ALSndPlayer *sndp = (ALSndPlayer *) node; + ALSndpEvent evt; + + do { + switch (sndp->nextEvent.type) { + case (AL_SNDP_API_EVT): + evt.common.type = AL_SNDP_API_EVT; + evt.common.state = (ALSoundState*)-1; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, sndp->frameTime); + break; + + default: + _handleEvent(sndp, (ALSndpEvent *)&sndp->nextEvent); + break; + } + sndp->nextDelta = alEvtqNextEvent(&sndp->evtq, &sndp->nextEvent); + + } while (sndp->nextDelta == 0); + sndp->curTime += sndp->nextDelta; + return sndp->nextDelta; +} + +void _handleEvent(ALSndPlayer *sndp, ALSndpEvent *event) +{ + ALVoiceConfig vc; + ALSound *snd; + ALVoice *voice; + ALPan pan; + f32 pitch; + ALSndpEvent evt; + ALMicroTime delta; + + s16 vol; + s16 tmp; + s32 vtmp; + ALSoundState *state; + + state = event->common.state; + snd = state->sound; + + + switch (event->msg.type) { + case (AL_SNDP_PLAY_EVT): + if (state->state != AL_STOPPED || !snd) + return; + + vc.fxBus = 0; /* effect buss 0 */ + vc.priority = state->priority; + vc.unityPitch = 0; + + voice = &state->voice; + alSynAllocVoice(sndp->drvr, voice, &vc); + + vol = (s16) ((s32) snd->envelope->attackVolume*state->vol/AL_VOL_FULL); + tmp = state->pan - AL_PAN_CENTER + snd->samplePan; + tmp = MAX(tmp, AL_PAN_LEFT); + pan = (ALPan) MIN(tmp, AL_PAN_RIGHT); + pitch = state->pitch; + delta = snd->envelope->attackTime; + + alSynStartVoice(sndp->drvr, voice, snd->wavetable); + state->state = AL_PLAYING; + + alSynSetPan(sndp->drvr, voice, pan); + alSynSetVol(sndp->drvr, voice, vol, delta); + alSynSetPitch(sndp->drvr, voice, pitch); + alSynSetFXMix(sndp->drvr, voice, state->fxMix); + + evt.common.type = AL_SNDP_DECAY_EVT; + evt.common.state = state; + delta = (ALMicroTime) _DivS32ByF32 (snd->envelope->attackTime, state->pitch); + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, delta); + break; + + case (AL_SNDP_STOP_EVT): + if (state->state != AL_PLAYING || !snd) + return; + + delta = (ALMicroTime) _DivS32ByF32 (snd->envelope->releaseTime, state->pitch); + alSynSetVol(sndp->drvr, &state->voice, 0, delta); + + if (delta) { + evt.common.type = AL_SNDP_END_EVT; + evt.common.state = state; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, delta); + state->state = AL_STOPPING; + } else { + /* note: this code is repeated in AL_SNDP_END_EVT */ + alSynStopVoice(sndp->drvr, &state->voice); + alSynFreeVoice(sndp->drvr, &state->voice); + _removeEvents(&sndp->evtq, state); + state->state = AL_STOPPED; + } + break; + + case (AL_SNDP_PAN_EVT): + state->pan = event->pan.pan; + if (state->state == AL_PLAYING && snd){ + tmp = state->pan - AL_PAN_CENTER + snd->samplePan; + tmp = MAX(tmp, AL_PAN_LEFT); + pan = (ALPan) MIN(tmp, AL_PAN_RIGHT); + alSynSetPan(sndp->drvr, &state->voice, pan); + } + break; + + case (AL_SNDP_PITCH_EVT): + /* Limit the pitch to a practical value even though we only need */ + /* to limit it to a non-zero number to avoid divide by zero. */ + if ((state->pitch = event->pitch.pitch) < MIN_RATIO) + state->pitch = MIN_RATIO; + + if (state->state == AL_PLAYING){ + alSynSetPitch(sndp->drvr, &state->voice, state->pitch); + } + break; + + case (AL_SNDP_FX_EVT): + state->fxMix = event->fx.mix; + if (state->state == AL_PLAYING) + alSynSetFXMix(sndp->drvr, &state->voice, state->fxMix); + break; + + case (AL_SNDP_VOL_EVT): + state->vol = event->vol.vol; + if (state->state == AL_PLAYING && snd){ + vtmp = snd->envelope->decayVolume * state->vol/AL_VOL_FULL; + alSynSetVol(sndp->drvr, &state->voice, (s16) vtmp, 1000); + } + break; + + case (AL_SNDP_DECAY_EVT): + /* + * The voice has theoretically reached its attack velocity, + * set up callback for release envelope - except for a looped sound + */ + if (snd->envelope->decayTime != -1){ + vtmp = snd->envelope->decayVolume * state->vol/AL_VOL_FULL; + delta = (ALMicroTime) _DivS32ByF32 (snd->envelope->decayTime, state->pitch); + alSynSetVol(sndp->drvr, &state->voice, (s16) vtmp, delta); + evt.common.type = AL_SNDP_STOP_EVT; + evt.common.state = state; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, delta); + } + break; + + case (AL_SNDP_END_EVT): + /* note: this code is repeated in AL_SNDP_STOP_EVT */ + alSynStopVoice(sndp->drvr, &state->voice); + alSynFreeVoice(sndp->drvr, &state->voice); + _removeEvents(&sndp->evtq, state); + state->state = AL_STOPPED; + break; + + default: + break; + } +} + +static +void _removeEvents(ALEventQueue *evtq, ALSoundState *state) +{ + ALLink *thisNode; + ALLink *nextNode; + ALEventListItem *thisItem; + ALEventListItem *nextItem; + ALSndpEvent *thisEvent; + OSIntMask mask; + + mask = osSetIntMask(OS_IM_NONE); + + thisNode = evtq->allocList.next; + while( thisNode != 0 ) { + nextNode = thisNode->next; + thisItem = (ALEventListItem *)thisNode; + nextItem = (ALEventListItem *)nextNode; + thisEvent = (ALSndpEvent *) &thisItem->evt; + if (thisEvent->common.state == state){ + if( nextItem ) + nextItem->delta += thisItem->delta; + alUnlink(thisNode); + alLink(thisNode, &evtq->freeList); + } + thisNode = nextNode; + } + + osSetIntMask(mask); +} + + +/* + This routine safely divides a signed 32-bit integer + by a floating point value. It avoids overflow by using + a double to store the result and then before truncating + to an integer it compares the result to the limit and + limits it on overflow. Underflow is handled automatically + by the CPU which limits the value to zero. + + Presently this routine is used to divide a time in usecs + by a pitch ratio. Since the time could be a very large number, + very small pitch ratios can cause the reult to overflow, + causing a floating point exception. +*/ +static +s32 _DivS32ByF32 (s32 i, f32 f) +{ + #define INT_MAX 2147483647 /* Should be in a limits.h file. */ + + f64 rd; + int ri; + +#ifdef _DEBUG + assert(f!=0); /* Caller must make sure we do not divide by zero! */ +#endif + + rd = i/f; /* Store result as a double to avoid overflow. */ + + if (rd > INT_MAX) /* Limit the value if necessary. */ + ri = INT_MAX; + else + ri = rd; + + return ri; +} diff --git a/lib/ultralib/src/audio/sndpplay.c b/lib/ultralib/src/audio/sndpplay.c new file mode 100644 index 0000000..ff5d123 --- /dev/null +++ b/lib/ultralib/src/audio/sndpplay.c @@ -0,0 +1,36 @@ +/*==================================================================== + * sndpplay.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpPlay(ALSndPlayer *sndp) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + + ALFailIf((sState + sndp->target)->state != AL_STOPPED, ERR_ALSNDPPLAY); + + evt.common.type = AL_SNDP_PLAY_EVT; + evt.common.state = &sState[sndp->target]; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/sndpplayat.c b/lib/ultralib/src/audio/sndpplayat.c new file mode 100644 index 0000000..b37f796 --- /dev/null +++ b/lib/ultralib/src/audio/sndpplayat.c @@ -0,0 +1,32 @@ +/*==================================================================== + * sndpplayat.c + * + * Copyright 1995, 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 "sndp.h" + +void alSndpPlayAt(ALSndPlayer *sndp, ALMicroTime delta) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + + evt.common.type = AL_SNDP_PLAY_EVT; + evt.common.state = &sState[sndp->target]; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, delta); +} + diff --git a/lib/ultralib/src/audio/sndpsetfxmix.c b/lib/ultralib/src/audio/sndpsetfxmix.c new file mode 100644 index 0000000..147c956 --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetfxmix.c @@ -0,0 +1,42 @@ +/*==================================================================== + * sndpsetfxmix.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetFXMix(ALSndPlayer *sndp, u8 mix) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + +#ifdef _DEBUG + if ((sndp->target >= sndp->maxSounds) || (sndp->target < 0)){ + __osError(ERR_ALSNDPSETPAR, 2, sndp->target, sndp->maxSounds-1); + return; + } +#endif + + evt.fx.type = AL_SNDP_FX_EVT; + evt.fx.state = &sState[sndp->target]; + evt.fx.mix = mix; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/sndpsetpan.c b/lib/ultralib/src/audio/sndpsetpan.c new file mode 100644 index 0000000..5f98648 --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetpan.c @@ -0,0 +1,42 @@ +/*==================================================================== + * sndpsetpan.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetPan(ALSndPlayer *sndp, ALPan pan) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + +#ifdef _DEBUG + if ((sndp->target >= sndp->maxSounds) || (sndp->target < 0)){ + __osError(ERR_ALSNDPSETPAR, 2, sndp->target, sndp->maxSounds-1); + return; + } +#endif + + evt.pan.type = AL_SNDP_PAN_EVT; + evt.pan.pan = pan; + evt.pan.state = &sState[sndp->target]; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/sndpsetpitch.c b/lib/ultralib/src/audio/sndpsetpitch.c new file mode 100644 index 0000000..0ee174c --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetpitch.c @@ -0,0 +1,48 @@ +/*==================================================================== + * sndpsetpitch.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetPitch(ALSndPlayer *sndp, f32 pitch) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + + /* + * If this is set during playback there will be + * a the envelope lengths won't be accurate - but you can still + * do it. + */ + +#ifdef _DEBUG + if ((sndp->target >= sndp->maxSounds) || (sndp->target < 0)){ + __osError(ERR_ALSNDPSETPAR, 2, sndp->target, sndp->maxSounds-1); + return; + } +#endif + + evt.pitch.type = AL_SNDP_PITCH_EVT; + evt.pitch.state = &sState[sndp->target]; + evt.pitch.pitch = pitch; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/sndpsetpriority.c b/lib/ultralib/src/audio/sndpsetpriority.c new file mode 100644 index 0000000..0d0fbc0 --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetpriority.c @@ -0,0 +1,38 @@ +/*==================================================================== + * sndpsetsound.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetPriority(ALSndPlayer *sndp, ALSndId id, u8 priority) +{ + ALSoundState *sState = sndp->sndState; + +#ifdef _DEBUG + if ((id >= sndp->maxSounds) || (id < 0)){ + __osError(ERR_ALSNDPSETPRIORITY, 2, id, sndp->maxSounds-1); + return; + } +#endif + + sState[id].priority = priority; +} + diff --git a/lib/ultralib/src/audio/sndpsetsound.c b/lib/ultralib/src/audio/sndpsetsound.c new file mode 100644 index 0000000..3d341ec --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetsound.c @@ -0,0 +1,36 @@ +/*==================================================================== + * sndpsetsound.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetSound(ALSndPlayer *sndp, ALSndId id) +{ +#ifdef _DEBUG + if ((id >= sndp->maxSounds) || (id < 0)){ + __osError(ERR_ALSNDPSETSOUND, 2, id, sndp->maxSounds-1); + return; + } +#endif + + sndp->target = id; +} + diff --git a/lib/ultralib/src/audio/sndpsetvol.c b/lib/ultralib/src/audio/sndpsetvol.c new file mode 100644 index 0000000..ad79f5f --- /dev/null +++ b/lib/ultralib/src/audio/sndpsetvol.c @@ -0,0 +1,42 @@ +/*==================================================================== + * sndpsetvol.c + * + * Copyright 1995, 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 "sndp.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSndpSetVol(ALSndPlayer *sndp, s16 vol) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + +#ifdef _DEBUG + if ((sndp->target >= sndp->maxSounds) || (sndp->target < 0)){ + __osError(ERR_ALSNDPSETPAR, 2, sndp->target, sndp->maxSounds-1); + return; + } +#endif + + evt.vol.type = AL_SNDP_VOL_EVT; + evt.vol.state = &sState[sndp->target]; + evt.vol.vol = vol; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/sndpstop.c b/lib/ultralib/src/audio/sndpstop.c new file mode 100644 index 0000000..69aead6 --- /dev/null +++ b/lib/ultralib/src/audio/sndpstop.c @@ -0,0 +1,35 @@ +/*==================================================================== + * sndpstop.c + * + * Copyright 1995, 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 "sndp.h" + +void alSndpStop(ALSndPlayer *sndp) +{ + ALSndpEvent evt; + ALSoundState *sState = sndp->sndState; + + /* + * Go immediately into the release phase + */ + evt.common.type = AL_SNDP_STOP_EVT; + evt.common.state = &sState[sndp->target]; + alEvtqPostEvent(&sndp->evtq, (ALEvent *)&evt, 0); +} + diff --git a/lib/ultralib/src/audio/synaddplayer.c b/lib/ultralib/src/audio/synaddplayer.c new file mode 100644 index 0000000..77efb29 --- /dev/null +++ b/lib/ultralib/src/audio/synaddplayer.c @@ -0,0 +1,34 @@ +/*==================================================================== + * synaddplayer.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> + +void alSynAddPlayer(ALSynth *drvr, ALPlayer *client) +{ + OSIntMask mask = osSetIntMask(OS_IM_NONE); + + client->samplesLeft = drvr->curSamples; + client->next = drvr->head; + drvr->head = client; + + osSetIntMask(mask); +} + diff --git a/lib/ultralib/src/audio/synallocfx.c b/lib/ultralib/src/audio/synallocfx.c new file mode 100644 index 0000000..e0e7f26 --- /dev/null +++ b/lib/ultralib/src/audio/synallocfx.c @@ -0,0 +1,32 @@ +/*==================================================================== + * synallocfx.c + * + * Copyright 1995, 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 "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]); +} + diff --git a/lib/ultralib/src/audio/synallocvoice.c b/lib/ultralib/src/audio/synallocvoice.c new file mode 100644 index 0000000..73d608d --- /dev/null +++ b/lib/ultralib/src/audio/synallocvoice.c @@ -0,0 +1,132 @@ +/*==================================================================== + * synallocvoice.c + * + * Copyright 1995, 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 "synthInternals.h" + +s32 _allocatePVoice(ALSynth *drvr, PVoice **pvoice, s16 priority); + +s32 alSynAllocVoice(ALSynth *drvr, ALVoice *voice, ALVoiceConfig *vc) +{ + PVoice *pvoice = 0; + ALFilter *f; + 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 = _allocatePVoice(drvr, &pvoice, vc->priority); + + if (pvoice) { /* if we were able to allocate a voice */ + + f = pvoice->channelKnob; + + if (stolen) { + + pvoice->offset = 512; + pvoice->vvoice->pvoice = 0; /* zero stolen voice */ + + /* + * ramp down stolen voice + */ + update = __allocParam(); + update->delta = drvr->paramSamples; + update->type = AL_FILTER_SET_VOLUME; + update->data.i = 0; + update->moredata.i = pvoice->offset - 64; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + + /* + * stop stolen voice + */ + update = __allocParam(); + if (update) { + update->delta = drvr->paramSamples + pvoice->offset; + update->type = AL_FILTER_STOP_VOICE; + update->next = 0; + (*f->setParam)(f, 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); +} + +s32 _allocatePVoice(ALSynth *drvr, PVoice **pvoice, s16 priority) +{ + ALLink *dl; + PVoice *pv; + s32 stolen = 0; + + if ((dl = drvr->pLameList.next) != 0) { /* check the lame list first */ + *pvoice = (PVoice *) dl; + alUnlink(dl); + alLink(dl, &drvr->pAllocList); + } else if ((dl = drvr->pFreeList.next) != 0) { /* from the free list */ + *pvoice = (PVoice *) dl; + alUnlink(dl); + alLink(dl, &drvr->pAllocList); + } else { /* steal one */ + for (dl = drvr->pAllocList.next; dl != 0; dl = dl->next) { + pv = (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; +} + diff --git a/lib/ultralib/src/audio/syndelete.c b/lib/ultralib/src/audio/syndelete.c new file mode 100644 index 0000000..900fe76 --- /dev/null +++ b/lib/ultralib/src/audio/syndelete.c @@ -0,0 +1,27 @@ +/*==================================================================== + * syndelete.c + * + * Copyright 1995, 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 "synthInternals.h" + +void alSynDelete(ALSynth *drvr) +{ + drvr->head = 0; +} + diff --git a/lib/ultralib/src/audio/synfreefx.c b/lib/ultralib/src/audio/synfreefx.c new file mode 100644 index 0000000..be436ea --- /dev/null +++ b/lib/ultralib/src/audio/synfreefx.c @@ -0,0 +1,26 @@ +/*==================================================================== + * synfreefx.c + * + * Copyright 1995, 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 "synthInternals.h" + +void alSynFreeFX(ALSynth *s, ALFxRef *fx) +{ +} + diff --git a/lib/ultralib/src/audio/synfreevoice.c b/lib/ultralib/src/audio/synfreevoice.c new file mode 100644 index 0000000..eaa71ac --- /dev/null +++ b/lib/ultralib/src/audio/synfreevoice.c @@ -0,0 +1,54 @@ +/*==================================================================== + * synfreevoice.c + * + * Copyright 1995, 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 <ultraerror.h> +#include <os_internal.h> +#include "synthInternals.h" + +#include <os.h> + +void alSynFreeVoice(ALSynth *drvr, ALVoice *voice) +{ + ALFilter *f; + ALFreeParam *update; + + if (voice->pvoice) { + + if (voice->pvoice->offset) { /* if voice was stolen */ + update = (ALFreeParam *)__allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * set voice data + */ + update->delta = drvr->paramSamples + voice->pvoice->offset; + update->type = AL_FILTER_FREE_VOICE; + update->pvoice = voice->pvoice; + + f = voice->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } else { + _freePVoice(drvr, voice->pvoice); + } + + voice->pvoice = 0; + + } +} diff --git a/lib/ultralib/src/audio/syngetfxref.c b/lib/ultralib/src/audio/syngetfxref.c new file mode 100644 index 0000000..b0fa577 --- /dev/null +++ b/lib/ultralib/src/audio/syngetfxref.c @@ -0,0 +1,33 @@ +/*==================================================================== + * syngetfxref.c + * + * Copyright 1995, 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 "synthInternals.h" + +ALFxRef alSynGetFXRef(ALSynth *s, s16 bus, s16 index) +{ + ALMainBus *m = (ALMainBus *) s->mainBus; + ALFilter **sources = m->sources; + + if (sources[0]->type == AL_FX) + return (ALFxRef)(&s->auxBus[bus].fx[index]); + else + return 0; +} + diff --git a/lib/ultralib/src/audio/syngetpriority.c b/lib/ultralib/src/audio/syngetpriority.c new file mode 100644 index 0000000..68de365 --- /dev/null +++ b/lib/ultralib/src/audio/syngetpriority.c @@ -0,0 +1,27 @@ +/*==================================================================== + * syngetpriority.c + * + * Copyright 1995, 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 "synthInternals.h" + +s16 alSynGetPriority(ALSynth *s, ALVoice *voice) +{ + return voice->priority; +} + diff --git a/lib/ultralib/src/audio/synremoveplayer.c b/lib/ultralib/src/audio/synremoveplayer.c new file mode 100644 index 0000000..0248a7e --- /dev/null +++ b/lib/ultralib/src/audio/synremoveplayer.c @@ -0,0 +1,49 @@ +/*==================================================================== + * synremoveplayer.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> + +void alSynRemovePlayer(ALSynth *drvr, ALPlayer *client) +{ + ALPlayer *thing; + ALPlayer *prev = 0; + + if (drvr->head != 0) + { + OSIntMask mask = osSetIntMask(OS_IM_NONE); + + for (thing = drvr->head; thing != 0; thing = thing->next) { + if (thing == client) { + if(prev) + prev->next = thing->next; + else + drvr->head = thing->next; + + client->next = 0; + break; + } + prev = thing; + } + + osSetIntMask(mask); + } +} + diff --git a/lib/ultralib/src/audio/synsetfxmix.c b/lib/ultralib/src/audio/synsetfxmix.c new file mode 100644 index 0000000..8c156ab --- /dev/null +++ b/lib/ultralib/src/audio/synsetfxmix.c @@ -0,0 +1,51 @@ +/*==================================================================== + * synsetfxmix.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSynSetFXMix(ALSynth *synth, ALVoice *v, u8 fxmix) +{ + ALParam *update; + ALFilter *f; + + if (v->pvoice) { + /* + * get new update struct from the free list + */ + update = __allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * set offset and fxmix data + */ + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_SET_FXAMT; + if (fxmix > 127) + fxmix = 127; + update->data.i = fxmix; + update->next = 0; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synsetfxparam.c b/lib/ultralib/src/audio/synsetfxparam.c new file mode 100644 index 0000000..b3991f6 --- /dev/null +++ b/lib/ultralib/src/audio/synsetfxparam.c @@ -0,0 +1,29 @@ +/*==================================================================== + * synsetfxparam.c + * + * Copyright 1995, 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 "synthInternals.h" + +void alSynSetFXParam(ALSynth *synth, ALFxRef fx, s16 paramID, void *param) +{ + ALFx *f = (ALFx *)fx; + + (*f->paramHdl)(f, (s32)paramID, param); +} + diff --git a/lib/ultralib/src/audio/synsetpan.c b/lib/ultralib/src/audio/synsetpan.c new file mode 100644 index 0000000..0d68538 --- /dev/null +++ b/lib/ultralib/src/audio/synsetpan.c @@ -0,0 +1,50 @@ +/*==================================================================== + * synsetpan.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSynSetPan(ALSynth *synth, ALVoice *v, u8 pan) +{ + ALParam *update; + ALFilter *f; + + if (v->pvoice) { + + /* + * get new update struct from the free list + */ + update = __allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * set offset and pan data + */ + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_SET_PAN; + update->data.i = pan; + update->next = 0; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synsetpitch.c b/lib/ultralib/src/audio/synsetpitch.c new file mode 100644 index 0000000..0bfb7ba --- /dev/null +++ b/lib/ultralib/src/audio/synsetpitch.c @@ -0,0 +1,50 @@ +/*==================================================================== + * synsetpitch.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSynSetPitch(ALSynth *synth, ALVoice *v, f32 pitch) +{ + ALParam *update; + ALFilter *f; + + if (v->pvoice) { + /* + * get new update struct from the free list + */ + + update = __allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * set offset and pitch data + */ + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_SET_PITCH; + update->data.f = pitch; + update->next = 0; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synsetpriority.c b/lib/ultralib/src/audio/synsetpriority.c new file mode 100644 index 0000000..c680bcc --- /dev/null +++ b/lib/ultralib/src/audio/synsetpriority.c @@ -0,0 +1,27 @@ +/*==================================================================== + * synsetpriority.c + * + * Copyright 1995, 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 <libaudio.h> + +void alSynSetPriority(ALSynth *s, ALVoice *voice, s16 priority) +{ + voice->priority = priority; +} + diff --git a/lib/ultralib/src/audio/synsetvol.c b/lib/ultralib/src/audio/synsetvol.c new file mode 100644 index 0000000..181c96f --- /dev/null +++ b/lib/ultralib/src/audio/synsetvol.c @@ -0,0 +1,50 @@ +/*==================================================================== + * synsetvol.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSynSetVol(ALSynth *synth, ALVoice *v, s16 volume, ALMicroTime t) +{ + ALParam *update; + ALFilter *f; + + if (v->pvoice) { + /* + * get new update struct from the free list + */ + update = __allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * set offset and volume data + */ + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_SET_VOLUME; + update->data.i = volume; + update->moredata.i = _timeToSamples(synth, t); + update->next = 0; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synstartvoice.c b/lib/ultralib/src/audio/synstartvoice.c new file mode 100644 index 0000000..9ad1d89 --- /dev/null +++ b/lib/ultralib/src/audio/synstartvoice.c @@ -0,0 +1,48 @@ +/*==================================================================== + * synstartvoice.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + +void alSynStartVoice(ALSynth *synth, ALVoice *v, ALWaveTable *table) +{ + ALStartParam *update; + ALFilter *f; + + if (v->pvoice) { + + update = (ALStartParam *)__allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + /* + * send the start message to the motion control filter + */ + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_START_VOICE; + update->wave = table; + update->next = 0; + update->unity = v->unityPitch; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synstartvoiceparam.c b/lib/ultralib/src/audio/synstartvoiceparam.c new file mode 100644 index 0000000..dbede0f --- /dev/null +++ b/lib/ultralib/src/audio/synstartvoiceparam.c @@ -0,0 +1,64 @@ +/*==================================================================== + * synquickstartvoice + * + * Copyright 1995, 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 "synthInternals.h" +#include <libaudio.h> +#include <ultraerror.h> +#include <os_internal.h> + +void alSynStartVoiceParams(ALSynth *s, ALVoice *v, ALWaveTable *w, + f32 pitch, s16 vol, ALPan pan, u8 fxmix, + ALMicroTime t) +{ + ALStartParamAlt *update; + ALFilter *f; + + if (v->pvoice) { + /* + * get new update struct from the free list + */ + update = (ALStartParamAlt *)__allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + if (fxmix > 127) + fxmix = 127; + + /* + * set offset and fxmix data + */ + update->delta = s->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 = _timeToSamples(s, t); + update->wave = w; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } + +} + + diff --git a/lib/ultralib/src/audio/synstopvoice.c b/lib/ultralib/src/audio/synstopvoice.c new file mode 100644 index 0000000..69c09d8 --- /dev/null +++ b/lib/ultralib/src/audio/synstopvoice.c @@ -0,0 +1,44 @@ +/*==================================================================== + * synstopvoice.c + * + * Copyright 1995, 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 "synthInternals.h" +#include <os_internal.h> +#include <ultraerror.h> + + +void alSynStopVoice(ALSynth *synth, ALVoice *v) +{ + ALParam *update; + ALFilter *f; + + if (v->pvoice) { + + update = __allocParam(); + ALFailIf(update == 0, ERR_ALSYN_NO_UPDATE); + + update->delta = synth->paramSamples + v->pvoice->offset; + update->type = AL_FILTER_STOP_VOICE; + update->next = 0; + + f = v->pvoice->channelKnob; + (*f->setParam)(f, AL_FILTER_ADD_UPDATE, update); + } +} + diff --git a/lib/ultralib/src/audio/synthInternals.h b/lib/ultralib/src/audio/synthInternals.h new file mode 100644 index 0000000..07c08bc --- /dev/null +++ b/lib/ultralib/src/audio/synthInternals.h @@ -0,0 +1,338 @@ +/*==================================================================== + * audioInternals.h + * + * Synopsis: + * + * 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. + *====================================================================*/ + +#ifndef __audioInternals__ +#define __audioInternals__ + +#include <libaudio.h> + +/* + * filter message ids + */ +enum { + AL_FILTER_FREE_VOICE, + AL_FILTER_SET_SOURCE, + AL_FILTER_ADD_SOURCE, + AL_FILTER_ADD_UPDATE, + AL_FILTER_RESET, + AL_FILTER_SET_WAVETABLE, +/* AL_FILTER_SET_DMA_PROC,*/ +/* AL_FILTER_SKIP_LOOP,*/ + AL_FILTER_SET_DRAM, + AL_FILTER_SET_PITCH, + AL_FILTER_SET_UNITY_PITCH, + AL_FILTER_START, +/* AL_FILTER_SET_DECAY,*/ +/* AL_FILTER_SET_FC,*/ + AL_FILTER_SET_STATE, + AL_FILTER_SET_VOLUME, + AL_FILTER_SET_PAN, + AL_FILTER_START_VOICE_ALT, + AL_FILTER_START_VOICE, + AL_FILTER_STOP_VOICE, + AL_FILTER_SET_FXAMT +}; + +#define AL_MAX_RSP_SAMPLES 160 + +/* + * buffer locations based on AL_MAX_RSP_SAMPLES + */ +#define AL_DECODER_IN 0 +#define AL_RESAMPLER_OUT 0 +#define AL_TEMP_0 0 +#define AL_DECODER_OUT 320 +#define AL_TEMP_1 320 +#define AL_TEMP_2 640 +#define AL_MAIN_L_OUT 1088 +#define AL_MAIN_R_OUT 1408 +#define AL_AUX_L_OUT 1728 +#define AL_AUX_R_OUT 2048 + +/* + * filter types + */ +enum { + AL_ADPCM, + AL_RESAMPLE, + AL_BUFFER, + AL_SAVE, + AL_ENVMIX, + AL_FX, + AL_AUXBUS, + AL_MAINBUS +}; + +typedef struct ALParam_s { + struct ALParam_s *next; + s32 delta; + s16 type; + union { + f32 f; + s32 i; + } data; + union { + f32 f; + s32 i; + } moredata; + union { + f32 f; + s32 i; + } stillmoredata; + union { + f32 f; + s32 i; + } yetstillmoredata; +} ALParam; + +typedef struct { + struct ALParam_s *next; + s32 delta; + s16 type; + s16 unity; /* disable resampler */ + f32 pitch; + s16 volume; + ALPan pan; + u8 fxMix; + s32 samples; + struct ALWaveTable_s *wave; +} ALStartParamAlt; + +typedef struct { + struct ALParam_s *next; + s32 delta; + s16 type; + s16 unity; /* disable resampler */ + struct ALWaveTable_s *wave; +} ALStartParam; + +typedef struct { + struct ALParam_s *next; + s32 delta; + s16 type; + struct PVoice_s *pvoice; +} ALFreeParam; + +typedef Acmd *(*ALCmdHandler)(void *, s16 *, s32, s32, Acmd *); +typedef s32 (*ALSetParam)(void *, s32, void *); + +typedef struct ALFilter_s { + struct ALFilter_s *source; + ALCmdHandler handler; + ALSetParam setParam; + s16 inp; + s16 outp; + s32 type; +} ALFilter; + +void alFilterNew(ALFilter *f, ALCmdHandler h, ALSetParam s, s32 type); + +#define AL_MAX_ADPCM_STATES 3 /* Depends on number of subframes + * per frame and loop length + */ +typedef struct { + ALFilter filter; + ADPCM_STATE *state; + ADPCM_STATE *lstate; + ALRawLoop loop; + struct ALWaveTable_s *table; + s32 bookSize; + ALDMAproc dma; + void *dmaState; + s32 sample; + s32 lastsam; + s32 first; + s32 memin; +} ALLoadFilter; + +void alLoadNew(ALLoadFilter *f, ALDMANew dma, ALHeap *hp); +Acmd *alAdpcmPull(void *f, s16 *outp, s32 byteCount, s32 sampleOffset, Acmd *p); +Acmd *alRaw16Pull(void *f, s16 *outp, s32 byteCount, s32 sampleOffset, Acmd *p); +s32 alLoadParam(void *filter, s32 paramID, void *param); + +typedef struct ALResampler_s { + ALFilter filter; + RESAMPLE_STATE *state; + f32 ratio; + s32 upitch; + f32 delta; + s32 first; + ALParam *ctrlList; + ALParam *ctrlTail; + s32 motion; +} ALResampler; + +typedef struct { + s16 fc; + s16 fgain; + union { + s16 fccoef[16]; + s64 force_aligned; + } fcvec; + POLEF_STATE *fstate; + s32 first; +} ALLowPass; + +typedef struct { + u32 input; + u32 output; + s16 ffcoef; + s16 fbcoef; + s16 gain; + f32 rsinc; + f32 rsval; + s32 rsdelta; + f32 rsgain; + ALLowPass *lp; + ALResampler *rs; +} ALDelay; + +typedef s32 (*ALSetFXParam)(void *, s32, void *); +typedef struct { + struct ALFilter_s filter; + s16 *base; + s16 *input; + u32 length; + ALDelay *delay; + u8 section_count; + ALSetFXParam paramHdl; +} ALFx; + +void alFxNew(ALFx *r, ALSynConfig *c, ALHeap *hp); +Acmd *alFxPull(void *f, s16 *outp, s32 out, s32 sampleOffset, Acmd *p); +s32 alFxParam(void *filter, s32 paramID, void *param); +s32 alFxParamHdl(void *filter, s32 paramID, void *param); + +#define AL_MAX_MAIN_BUS_SOURCES 1 +typedef struct ALMainBus_s { + ALFilter filter; + s32 sourceCount; + s32 maxSources; + ALFilter **sources; +} ALMainBus; + +void alMainBusNew(ALMainBus *m, void *ptr, s32 len); +Acmd *alMainBusPull(void *f, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p); +s32 alMainBusParam(void *filter, s32 paramID, void *param); + +#define AL_MAX_AUX_BUS_SOURCES 8 +#define AL_MAX_AUX_BUS_FX 1 +typedef struct ALAuxBus_s { + ALFilter filter; + s32 sourceCount; + s32 maxSources; + ALFilter **sources; + ALFx fx[AL_MAX_AUX_BUS_FX]; +} ALAuxBus; + +void alAuxBusNew(ALAuxBus *m, void *ptr, s32 len); +Acmd *alAuxBusPull(void *f, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p); +s32 alAuxBusParam(void *filter, s32 paramID, void *param); + +void alResampleNew(ALResampler *r, ALHeap *hp); +Acmd *alResamplePull(void *f, s16 *outp, s32 out, s32 sampleOffset, Acmd *p); +s32 alResampleParam(void *f, s32 paramID, void *param); + +typedef struct ALSave_s { + ALFilter filter; + s32 dramout; + s32 first; +} ALSave; + +void alSaveNew(ALSave *r); +Acmd *alSavePull(void *f, s16 *outp, s32 outCount, s32 sampleOffset, Acmd *p); +s32 alSaveParam(void *f, s32 paramID, void *param); + +typedef struct ALEnvMixer_s { + ALFilter filter; + ENVMIX_STATE *state; + s16 pan; + s16 volume; + s16 cvolL; + s16 cvolR; + s16 dryamt; + s16 wetamt; + u16 lratl; + s16 lratm; + s16 ltgt; + u16 rratl; + s16 rratm; + s16 rtgt; + s32 delta; + s32 segEnd; + s32 first; + ALParam *ctrlList; + ALParam *ctrlTail; + ALFilter **sources; + s32 motion; +} ALEnvMixer; + +void alEnvmixerNew(ALEnvMixer *e, ALHeap *hp); +Acmd *alEnvmixerPull(void *f, s16 *outp, s32 out, s32 sampleOffset, Acmd *p); +s32 alEnvmixerParam(void *filter, s32 paramID, void *param); + + +/* + * heap stuff + */ +typedef struct { + s32 magic; /* check structure integrety */ + s32 size; /* size of this allocated block */ + u8 *file; /* file that this alloc was called from */ + s32 line; /* line that it was called from */ + s32 count; /* heap call number */ + s32 pad0; + s32 pad1; + s32 pad2; /* Make it 32 bytes */ +} HeapInfo; + +#define AL_CACHE_ALIGN 15 + +/* + * synth stuff + */ + +typedef struct PVoice_s { + ALLink node; + struct ALVoice_s *vvoice; + ALFilter *channelKnob; + ALLoadFilter decoder; + ALResampler resampler; + ALEnvMixer envmixer; + s32 offset; +} PVoice; + +/* + * prototypes for private driver functions + */ +ALParam *__allocParam(void); +void __freeParam(ALParam *param); +void _freePVoice(ALSynth *drvr, PVoice *pvoice); +void _collectPVoices(ALSynth *drvr); + +s32 _timeToSamples(ALSynth *ALSynth, s32 micros); +ALMicroTime _samplesToTime(ALSynth *synth, s32 samples); + +void _init_lpfilter(ALLowPass *lp); + +#endif + diff --git a/lib/ultralib/src/audio/synthesizer.c b/lib/ultralib/src/audio/synthesizer.c new file mode 100644 index 0000000..d42a21a --- /dev/null +++ b/lib/ultralib/src/audio/synthesizer.c @@ -0,0 +1,327 @@ +/*==================================================================== + * synthesizer.c + * + * 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 "synthInternals.h" +#include <assert.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +#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 __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; + +#ifdef _DEBUG + assert(drvr->head); +#endif + + *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; +} + + + diff --git a/lib/ultralib/src/debug/osint_debug.h b/lib/ultralib/src/debug/osint_debug.h new file mode 100644 index 0000000..b493035 --- /dev/null +++ b/lib/ultralib/src/debug/osint_debug.h @@ -0,0 +1,11 @@ +#include "PR/os_internal.h" + +extern s32 __osThprofFlag; +extern void (*__osThprofFunc)(OSThread*); +extern u32 __osThprofLastTimer; +extern u32 __osThprofCount; +extern __OSThreadprofile_s thprof[THPROF_IDMAX]; +extern u64 __osThprofHeap[THPROF_STACKSIZE]; +extern void* __osThprofStack; + +void osThreadProfileCallback(OSThread*); diff --git a/lib/ultralib/src/debug/threadprofile.c b/lib/ultralib/src/debug/threadprofile.c new file mode 100644 index 0000000..e383773 --- /dev/null +++ b/lib/ultralib/src/debug/threadprofile.c @@ -0,0 +1,22 @@ +#include "osint_debug.h" + +#include "macros.h" + +s32 __osThprofFlag = 0; +void (*__osThprofFunc)(OSThread*) = NULL; + +u32 __osThprofLastTimer; +u32 __osThprofCount; +__OSThreadprofile_s thprof[THPROF_IDMAX] ALIGNED(0x10); +u64 __osThprofHeap[THPROF_STACKSIZE] ALIGNED(0x10); +void* __osThprofStack; + +void osThreadProfileCallback(OSThread* osthread) { + register u32 now_time = osGetCount(); + __OSThreadprofile_s* thprof = osthread->thprof; + + thprof->time += now_time - __osThprofLastTimer; + thprof->count++; + __osThprofCount++; + __osThprofLastTimer = now_time; +} diff --git a/lib/ultralib/src/debug/threadprofileclear.c b/lib/ultralib/src/debug/threadprofileclear.c new file mode 100644 index 0000000..42788f8 --- /dev/null +++ b/lib/ultralib/src/debug/threadprofileclear.c @@ -0,0 +1,11 @@ +#include "osint_debug.h" + +void osThreadProfileClear(OSId id) { + register OSIntMask saveMask = __osDisableInt(); + + thprof[id].flag = 0; + thprof[id].count = 0; + thprof[id].time = 0; + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/debug/threadprofileinit.c b/lib/ultralib/src/debug/threadprofileinit.c new file mode 100644 index 0000000..7fef229 --- /dev/null +++ b/lib/ultralib/src/debug/threadprofileinit.c @@ -0,0 +1,16 @@ +#include "osint_debug.h" + +void osThreadProfileInit(void) { + register u32 saveMask = __osDisableInt(); + OSId i; + + __osThprofFunc = NULL; + __osThprofFlag = 1; + __osThprofCount = 0; + __osThprofStack = &__osThprofHeap[(THPROF_STACKSIZE - 8) / sizeof(*__osThprofHeap)]; + __osRestoreInt(saveMask); + + for (i = 0; i < THPROF_IDMAX; i++) { + osThreadProfileClear(i); + } +} diff --git a/lib/ultralib/src/debug/threadprofilereadcount.c b/lib/ultralib/src/debug/threadprofilereadcount.c new file mode 100644 index 0000000..c12d313 --- /dev/null +++ b/lib/ultralib/src/debug/threadprofilereadcount.c @@ -0,0 +1,31 @@ +#include "osint_debug.h" + +u32 osThreadProfileReadCount(OSId id) { + if (!__osThprofFlag) { + __osError(139, 0); + return 0; + } + + if (id >= THPROF_IDMAX) { + __osError(143, 1, id); + return 0; + } + return thprof[id].count; +} + +u32 osThreadProfileReadCountTh(OSThread* thread) { + OSId id; + + if (!__osThprofFlag) { + __osError(141, 0); + return 0; + } + + id = osGetThreadId(thread); + + if (id >= THPROF_IDMAX) { + __osError(145, 1, id); + return 0; + } + return thprof[id].count; +} diff --git a/lib/ultralib/src/debug/threadprofilereadtime.c b/lib/ultralib/src/debug/threadprofilereadtime.c new file mode 100644 index 0000000..c5c4cca --- /dev/null +++ b/lib/ultralib/src/debug/threadprofilereadtime.c @@ -0,0 +1,43 @@ +#include "osint_debug.h" + +OSTime osThreadProfileReadTime(OSId id) { + OSTime adjust = 0; + u32 now_time = osGetCount(); + + if (!__osThprofFlag) { + __osError(140, 0); + return 0; + } + if (id >= THPROF_IDMAX) { + __osError(144, 1, id); + return 0; + } + + if (id == osGetThreadId(NULL) && __osThprofFunc != NULL) { + adjust = now_time - __osThprofLastTimer; + } + return thprof[id].time + adjust; +} + +OSTime osThreadProfileReadTimeTh(OSThread* thread) { + OSId id; + OSTime adjust = 0; + u32 now_time = osGetCount(); + + if (!__osThprofFlag) { + __osError(142, 0); + return 0; + } + + id = osGetThreadId(thread); + + if (id >= THPROF_IDMAX) { + __osError(146, 1, id); + return 0; + } + + if (id == osGetThreadId(NULL) && __osThprofFunc != NULL) { + adjust = now_time - __osThprofLastTimer; + } + return thprof[id].time + adjust; +} diff --git a/lib/ultralib/src/debug/threadprofilestart.c b/lib/ultralib/src/debug/threadprofilestart.c new file mode 100644 index 0000000..0891ad7 --- /dev/null +++ b/lib/ultralib/src/debug/threadprofilestart.c @@ -0,0 +1,20 @@ +#include "osint_debug.h" + +void osThreadProfileStart(void) { + register u32 saveMask; + + if (!__osThprofFlag) { + __osError(136, 0); + return; + } + if (__osThprofFunc != NULL) { + __osError(137, 0); + return; + } + + saveMask = __osDisableInt(); + + __osThprofLastTimer = osGetCount(); + __osThprofFunc = osThreadProfileCallback; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/debug/threadprofilestop.c b/lib/ultralib/src/debug/threadprofilestop.c new file mode 100644 index 0000000..666d7cd --- /dev/null +++ b/lib/ultralib/src/debug/threadprofilestop.c @@ -0,0 +1,34 @@ +#include "osint_debug.h" + +void osThreadProfileStop(void) { + register u32 saveMask; + int i; + OSId id; + u32 now_time = osGetCount(); + + saveMask = __osDisableInt(); + + if (__osThprofFlag == 0) { + __osRestoreInt(saveMask); + __osError(138, 0); + return; + } + + if (__osThprofFunc != NULL) { + id = osGetThreadId(0); + + if (id < THPROF_IDMAX) { + thprof[id].time += now_time - __osThprofLastTimer; + } else { + __osRestoreInt(saveMask); + __osError(147, 1, id); + saveMask = __osDisableInt(); + } + } + __osThprofFunc = NULL; + + for (i = 0; i < THPROF_IDMAX; i++) { + thprof[i].flag = 0; + } + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/flash/flashallerase.c b/lib/ultralib/src/flash/flashallerase.c new file mode 100644 index 0000000..c66dbd6 --- /dev/null +++ b/lib/ultralib/src/flash/flashallerase.c @@ -0,0 +1,31 @@ +#include "PR/os_internal.h" + +s32 osFlashAllErase(void) { + u32 status; + OSTimer mytimer; + OSMesgQueue timerMesgQueue; + OSMesg dummy; + + // start chip erase operation + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_CHIP_ERASE); + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_EXECUTE_ERASE); + + // wait for completion by polling erase-busy flag + osCreateMesgQueue(&timerMesgQueue, &dummy, 1); + do { + osSetTimer(&mytimer, OS_USEC_TO_CYCLES(15000), 0, &timerMesgQueue, &dummy); + osRecvMesg(&timerMesgQueue, &dummy, OS_MESG_BLOCK); + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + } while ((status & FLASH_STATUS_ERASE_BUSY) == FLASH_STATUS_ERASE_BUSY); + + // check erase operation status, clear status + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + osFlashClearStatus(); + + // check for success + if (((status & 0xFF) == 8) || ((status & 0xFF) == 0x48) || ((status & 8) == 8)) { + return FLASH_STATUS_ERASE_OK; + } else { + return FLASH_STATUS_ERASE_ERROR; + } +} diff --git a/lib/ultralib/src/flash/flashallerasethrough.c b/lib/ultralib/src/flash/flashallerasethrough.c new file mode 100644 index 0000000..9e52b97 --- /dev/null +++ b/lib/ultralib/src/flash/flashallerasethrough.c @@ -0,0 +1,7 @@ +#include "PR/os_internal.h" + +void osFlashAllEraseThrough(void) { + // start chip erase operation, no waiting for completion + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_CHIP_ERASE); + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_EXECUTE_ERASE); +} diff --git a/lib/ultralib/src/flash/flashchange.c b/lib/ultralib/src/flash/flashchange.c new file mode 100644 index 0000000..e667668 --- /dev/null +++ b/lib/ultralib/src/flash/flashchange.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" + +void osFlashChange(u32 flash_num) { + __osFlashHandler.baseAddress = PHYS_TO_K1((FLASH_START_ADDR + flash_num * FLASH_SIZE)); + __osFlashHandler.type = DEVICE_TYPE_FLASH + flash_num; + return; +} diff --git a/lib/ultralib/src/flash/flashcheckeraseend.c b/lib/ultralib/src/flash/flashcheckeraseend.c new file mode 100644 index 0000000..47faf5c --- /dev/null +++ b/lib/ultralib/src/flash/flashcheckeraseend.c @@ -0,0 +1,21 @@ +#include "PR/os_internal.h" + +s32 osFlashCheckEraseEnd(void) { + u8 status; + + osFlashReadStatus(&status); + + if (!(status & FLASH_STATUS_ERASE_BUSY)) { + // not busy, read and clear status + osFlashReadStatus(&status); + osFlashClearStatus(); + + // check for success + if (((status & 0xFF) == 8) || ((status & 0xFF) == 0x48) || ((status & 8) == 8)) { + return FLASH_STATUS_ERASE_OK; + } else { + return FLASH_STATUS_ERASE_ERROR; + } + } + return FLASH_STATUS_ERASE_BUSY; +} diff --git a/lib/ultralib/src/flash/flashclearstatus.c b/lib/ultralib/src/flash/flashclearstatus.c new file mode 100644 index 0000000..7622f9c --- /dev/null +++ b/lib/ultralib/src/flash/flashclearstatus.c @@ -0,0 +1,10 @@ +#include "PR/os_internal.h" + +void osFlashClearStatus(void) { + // select status mode + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_STATUS); + // clear status + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress, 0); + + return; +} diff --git a/lib/ultralib/src/flash/flashgetaddr.c b/lib/ultralib/src/flash/flashgetaddr.c new file mode 100644 index 0000000..3fe2e37 --- /dev/null +++ b/lib/ultralib/src/flash/flashgetaddr.c @@ -0,0 +1,7 @@ +#include "PR/os_internal.h" + +u32 __osFlashGetAddr(u32 page_num) { + u32 devAddr = (__osFlashVersion == OLD_FLASH) ? page_num << 6 : page_num << 7; + + return devAddr; +} diff --git a/lib/ultralib/src/flash/flashinit.c b/lib/ultralib/src/flash/flashinit.c new file mode 100644 index 0000000..9b51a25 --- /dev/null +++ b/lib/ultralib/src/flash/flashinit.c @@ -0,0 +1,43 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" +#include "macros.h" + +OSMesgQueue __osFlashMessageQ ALIGNED(8); +OSMesg __osFlashMsgBuf[1]; +OSPiHandle __osFlashHandler ALIGNED(8); +s32 __osFlashVersion; +OSIoMesg __osFlashMsg ALIGNED(8); +u32 __osFlashID[4] ALIGNED(8); + +OSPiHandle* osFlashInit(void) { + u32 flash_type; + u32 flash_maker; + + osCreateMesgQueue(&__osFlashMessageQ, __osFlashMsgBuf, ARRLEN(__osFlashMsgBuf)); + + if (__osFlashHandler.baseAddress == PHYS_TO_K1(FLASH_START_ADDR)) { + return &__osFlashHandler; + } + + __osFlashHandler.type = DEVICE_TYPE_FLASH; + __osFlashHandler.baseAddress = PHYS_TO_K1(FLASH_START_ADDR); + __osFlashHandler.latency = FLASH_LATENCY; + __osFlashHandler.pulse = FLASH_PULSE; + __osFlashHandler.pageSize = FLASH_PAGE_SIZE; + __osFlashHandler.relDuration = FLASH_REL_DURATION; + __osFlashHandler.domain = PI_DOMAIN2; + __osFlashHandler.speed = 0; + + bzero(&__osFlashHandler.transferInfo, sizeof(__OSTranxInfo)); + + osEPiLinkHandle(&__osFlashHandler); + osFlashReadId(&flash_type, &flash_maker); + + if (flash_maker == FLASH_VERSION_MX_C || flash_maker == FLASH_VERSION_MX_A || flash_maker == FLASH_VERSION_MX_PROTO_A) { + __osFlashVersion = OLD_FLASH; + } else { + __osFlashVersion = NEW_FLASH; + } + + return &__osFlashHandler; +} diff --git a/lib/ultralib/src/flash/flashreadarray.c b/lib/ultralib/src/flash/flashreadarray.c new file mode 100644 index 0000000..6134d33 --- /dev/null +++ b/lib/ultralib/src/flash/flashreadarray.c @@ -0,0 +1,49 @@ +#include "PR/os_internal.h" + +s32 osFlashReadArray(OSIoMesg* mb, s32 priority, u32 page_num, void* dramAddr, u32 n_pages, OSMesgQueue* mq) { + u32 ret; + u32 tmp; + u32 end_page; + u32 one_dma_pages; + + // select read array mode + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_READ_ARRAY); + // dummy read? + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &tmp); + + // DMA requested pages + mb->hdr.pri = priority; + mb->hdr.retQueue = mq; + mb->dramAddr = dramAddr; + + end_page = page_num + n_pages - 1; + + if ((end_page & 0xF00) != (page_num & 0xF00)) { + one_dma_pages = 256 - (page_num & 0xFF); + n_pages -= one_dma_pages; + mb->size = one_dma_pages * FLASH_BLOCK_SIZE; + mb->devAddr = __osFlashGetAddr(page_num); + osEPiStartDma(&__osFlashHandler, mb, OS_READ); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + page_num = (page_num + 256) & 0xF00; + mb->dramAddr = (u32)mb->dramAddr + mb->size; + } + + while (n_pages > 256) { + one_dma_pages = 256; + n_pages -= 256; + mb->size = one_dma_pages * FLASH_BLOCK_SIZE; + mb->devAddr = __osFlashGetAddr(page_num); + osEPiStartDma(&__osFlashHandler, mb, OS_READ); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + page_num += 256; + mb->dramAddr = (u32)mb->dramAddr + mb->size; + } + + mb->size = n_pages * FLASH_BLOCK_SIZE; + mb->devAddr = __osFlashGetAddr(page_num); + + ret = osEPiStartDma(&__osFlashHandler, mb, OS_READ); + + return ret; +} diff --git a/lib/ultralib/src/flash/flashreadid.c b/lib/ultralib/src/flash/flashreadid.c new file mode 100644 index 0000000..7c8a2c0 --- /dev/null +++ b/lib/ultralib/src/flash/flashreadid.c @@ -0,0 +1,27 @@ +#include "PR/os_internal.h" + +void osFlashReadId(u32* flash_type, u32* flash_maker) { + u8 tmp; + + // why read status ? + osFlashReadStatus(&tmp); + + // select silicon id read mode + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_ID); + + // read silicon id using DMA + __osFlashMsg.hdr.pri = OS_MESG_PRI_NORMAL; + __osFlashMsg.hdr.retQueue = &__osFlashMessageQ; + __osFlashMsg.dramAddr = __osFlashID; + __osFlashMsg.devAddr = 0; + __osFlashMsg.size = 2 * sizeof(u32); + + osInvalDCache(__osFlashID, sizeof(__osFlashID)); + osEPiStartDma(&__osFlashHandler, &__osFlashMsg, OS_READ); + osRecvMesg(&__osFlashMessageQ, NULL, OS_MESG_BLOCK); + + *flash_type = __osFlashID[0]; + *flash_maker = __osFlashID[1]; + + return; +} diff --git a/lib/ultralib/src/flash/flashreadstatus.c b/lib/ultralib/src/flash/flashreadstatus.c new file mode 100644 index 0000000..6bb582b --- /dev/null +++ b/lib/ultralib/src/flash/flashreadstatus.c @@ -0,0 +1,17 @@ +#include "PR/os_internal.h" + +void osFlashReadStatus(u8* flash_status) { + u32 status; + + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_STATUS); + // read status + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + + // why twice ? + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_STATUS); + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + + *flash_status = status & 0xFF; + + return; +} diff --git a/lib/ultralib/src/flash/flashreinit.c b/lib/ultralib/src/flash/flashreinit.c new file mode 100644 index 0000000..deb6070 --- /dev/null +++ b/lib/ultralib/src/flash/flashreinit.c @@ -0,0 +1,14 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" + +OSPiHandle* osFlashReInit(u8 latency, u8 pulse, u8 page_size, u8 rel_duration, u32 start) { + __osFlashHandler.baseAddress = PHYS_TO_K1(start); + __osFlashHandler.type++; + __osFlashHandler.latency = latency; + __osFlashHandler.pulse = pulse; + __osFlashHandler.pageSize = page_size; + __osFlashHandler.relDuration = rel_duration; + __osFlashHandler.domain = PI_DOMAIN2; + + return &__osFlashHandler; +} diff --git a/lib/ultralib/src/flash/flashsectorerase.c b/lib/ultralib/src/flash/flashsectorerase.c new file mode 100644 index 0000000..fcccc6e --- /dev/null +++ b/lib/ultralib/src/flash/flashsectorerase.c @@ -0,0 +1,31 @@ +#include "PR/os_internal.h" + +s32 osFlashSectorErase(u32 page_num) { + u32 status; + OSTimer mytimer; + OSMesgQueue timerMesgQueue; + OSMesg dummy; + + // start sector erase operation + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_SECTOR_ERASE | page_num); + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_EXECUTE_ERASE); + + // wait for completion by polling erase-busy flag + osCreateMesgQueue(&timerMesgQueue, &dummy, 1); + + do { + osSetTimer(&mytimer, OS_USEC_TO_CYCLES(12500), 0, &timerMesgQueue, &dummy); + osRecvMesg(&timerMesgQueue, &dummy, OS_MESG_BLOCK); + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + } while ((status & FLASH_STATUS_ERASE_BUSY) == FLASH_STATUS_ERASE_BUSY); + + // check erase operation status, clear status + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + osFlashClearStatus(); + + if (((status & 0xFF) == 8) || ((status & 0xFF) == 0x48) || ((status & 8) == 8)) { + return FLASH_STATUS_ERASE_OK; + } else { + return FLASH_STATUS_ERASE_ERROR; + } +} diff --git a/lib/ultralib/src/flash/flashsectorerasethrough.c b/lib/ultralib/src/flash/flashsectorerasethrough.c new file mode 100644 index 0000000..52097e1 --- /dev/null +++ b/lib/ultralib/src/flash/flashsectorerasethrough.c @@ -0,0 +1,7 @@ +#include "PR/os_internal.h" + +void osFlashSectorEraseThrough(u32 page_num) { + // start sector erase operation + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_SECTOR_ERASE | page_num); + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_EXECUTE_ERASE); +} diff --git a/lib/ultralib/src/flash/flashwritearray.c b/lib/ultralib/src/flash/flashwritearray.c new file mode 100644 index 0000000..555f1df --- /dev/null +++ b/lib/ultralib/src/flash/flashwritearray.c @@ -0,0 +1,33 @@ +#include "PR/os_internal.h" + +s32 osFlashWriteArray(u32 page_num) { + u32 status; + OSTimer mytimer; + OSMesgQueue timerMesgQueue; + OSMesg dummy; + + if (__osFlashVersion == NEW_FLASH) { + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_PAGE_PROGRAM); + } + + // start program page operation + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_PROGRAM_PAGE | page_num); + + // wait for completion by polling write-busy flag + osCreateMesgQueue(&timerMesgQueue, &dummy, 1); + do { + osSetTimer(&mytimer, OS_USEC_TO_CYCLES(200), 0, &timerMesgQueue, &dummy); + osRecvMesg(&timerMesgQueue, &dummy, OS_MESG_BLOCK); + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + } while ((status & FLASH_STATUS_WRITE_BUSY) == FLASH_STATUS_WRITE_BUSY); + + // check program operation status, clear status + osEPiReadIo(&__osFlashHandler, __osFlashHandler.baseAddress, &status); + osFlashClearStatus(); + + if (((status & 0xFF) == 4) || ((status & 0xFF) == 0x44) || ((status & 4) == 4)) { + return FLASH_STATUS_WRITE_OK; + } else { + return FLASH_STATUS_WRITE_ERROR; + } +} diff --git a/lib/ultralib/src/flash/flashwritebuffer.c b/lib/ultralib/src/flash/flashwritebuffer.c new file mode 100644 index 0000000..8cbd0c9 --- /dev/null +++ b/lib/ultralib/src/flash/flashwritebuffer.c @@ -0,0 +1,19 @@ +#include "PR/os_internal.h" + +s32 osFlashWriteBuffer(OSIoMesg* mb, s32 priority, void* dramAddr, OSMesgQueue* mq) { + s32 ret; + + // select page program mode + osEPiWriteIo(&__osFlashHandler, __osFlashHandler.baseAddress | FLASH_CMD_REG, FLASH_CMD_PAGE_PROGRAM); + + // DMA 128-byte page + mb->hdr.pri = priority; + mb->hdr.retQueue = mq; + mb->dramAddr = dramAddr; + mb->devAddr = 0; + mb->size = FLASH_BLOCK_SIZE; + + ret = osEPiStartDma(&__osFlashHandler, mb, OS_WRITE); + + return ret; +} diff --git a/lib/ultralib/src/gio/giointerrupt.c b/lib/ultralib/src/gio/giointerrupt.c new file mode 100644 index 0000000..3abc04f --- /dev/null +++ b/lib/ultralib/src/gio/giointerrupt.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" +#include "../io/piint.h" + +void __osGIOInterrupt(s32 value) { + __osPiGetAccess(); + __osGIORawInterrupt(value); + __osPiRelAccess(); +} diff --git a/lib/ultralib/src/gio/giorawinterrupt.c b/lib/ultralib/src/gio/giorawinterrupt.c new file mode 100644 index 0000000..64652d3 --- /dev/null +++ b/lib/ultralib/src/gio/giorawinterrupt.c @@ -0,0 +1,18 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +void __osGIORawInterrupt(s32 value) { + register u32 stat; + + stat = IO_READ(PI_STATUS_REG); + while (stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + stat = IO_READ(PI_STATUS_REG); + } + + IO_WRITE(GIO_GIO_INTR_REG, value); + + stat = IO_READ(PI_STATUS_REG); + while (stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + stat = IO_READ(PI_STATUS_REG); + } +} diff --git a/lib/ultralib/src/gt/Makefile b/lib/ultralib/src/gt/Makefile new file mode 100644 index 0000000..b0868fd --- /dev/null +++ b/lib/ultralib/src/gt/Makefile @@ -0,0 +1,19 @@ +#!smake +# +# Makefile for the gt subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + + +# LCOPTS = -mips2 -non_shared -fullwarn -G 0 + +LCINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include + +CFILES = dumpturbo.c gt.c + +OBJECTS = $(CFILES:.c=.o) + +default: $(OBJECTS) + +include $(COMMONRULES) diff --git a/lib/ultralib/src/gt/dumpturbo.c b/lib/ultralib/src/gt/dumpturbo.c new file mode 100644 index 0000000..095c8a4 --- /dev/null +++ b/lib/ultralib/src/gt/dumpturbo.c @@ -0,0 +1,255 @@ + +/************************************************************************** + * * + * 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. * + * * + *************************************************************************/ + +/* + * Interpret & dump a turbo display list for RSPSIM debugging + * + */ + +#include <ultra64.h> +#include <gt.h> + +#undef PRINTF +#define PRINTF rmonPrintf + + +#define TX_MAX 100 +static u32 textures[TX_MAX]; +static u32 numtextures; + +#define UNSEG_ADDR(sa) ((u32 *) (((globp)? \ + (((int)(sa) & 0x00ffffff) + \ + globp->sp.segBases[(int)(sa)>>24]) \ + : (int)(sa)) | 0x80000000)) +#define PHYS(a) ((int) ((int)(a) & 0x7fffffff)) +#define UNPHYS(a) ((u32 *) ((int)(a) | 0x80000000)) + +#define DOPRINT(a,r) \ +rmonPrintf("UNSEG: %x ->(seg%x = %06x)-> %08x\n",(int)(a),(int)(a)>>24,((globp)?(globp->sp.segBases[(int)(a)>>24]):0), (int)(r)) + + + +#define UCODE_SIZE_MAX (4096*1) +void +gtDumpTurbo(OSTask *tp,u8 flags) +{ + int i; + gtGfx *gtlistp; + gtGlobState *globp=0; + gtState *statep; + u32 dat,*datp,*addr; + + + PRINTF("\nGBI_DUMP_START:\n"); + PRINTF("$ %08x\n",PHYS(tp)); + + for (i=(int)tp; i<(int)tp+sizeof(OSTask); i+=4) { + PRINTF("<%08x\n",(int) *((u32 *) i)); + } + +#if 1 + PRINTF("? %08x\n",PHYS(tp->t.ucode_boot)); + for (i=(int)tp->t.ucode_boot; + i<(int)tp->t.ucode_boot+tp->t.ucode_boot_size; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + + PRINTF("? %08x\n",PHYS(tp->t.ucode)); + for (i=(int)tp->t.ucode; i<(int)tp->t.ucode+UCODE_SIZE_MAX; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + + PRINTF("? %08x\n",PHYS(tp->t.ucode_data)); + for (i=(int)tp->t.ucode_data; + i<(int)tp->t.ucode_data+tp->t.ucode_data_size; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + +#endif + + + + gtlistp = (gtGfx *) tp->t.data_ptr; + PRINTF("@ %08x\n",PHYS(gtlistp)); + +/* + * Dump turbo display list + */ + while (gtlistp->obj.statep) { + PRINTF(">%08x\n",(int) gtlistp->obj.gstatep); + PRINTF("-%08x\n",(int) gtlistp->obj.statep); + PRINTF("-%08x\n",(int) gtlistp->obj.vtxp); + PRINTF("-%08x\n",(int) gtlistp->obj.trip); + gtlistp++; + } + PRINTF(">%08x\n",(int) gtlistp->obj.gstatep); + PRINTF("-%08x\n",(int) gtlistp->obj.statep); + PRINTF("-%08x\n",(int) gtlistp->obj.vtxp); + PRINTF("-%08x\n",(int) gtlistp->obj.trip); + +/* + * Dump infor pointed to by DL + */ + gtlistp = (gtGfx *) tp->t.data_ptr; + while (gtlistp->obj.statep) { +/*rmonPrintf("=============== DUMP A DL ENTRY (%x)\n",(int)gtlistp);*/ + +/* + * Dump global state + */ + if (gtlistp->obj.gstatep) { + addr = UNSEG_ADDR(gtlistp->obj.gstatep); + globp = (gtGlobState *) addr; +/*rmonPrintf("======= DUMP GlobalState (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + (u8 *) datp < (u8 *) addr + sizeof(gtGlobState); + datp++) { + PRINTF("+%08x\n",*datp); + } + if (globp->sp.rdpCmds) { + addr = UNSEG_ADDR(globp->sp.rdpCmds); +/*rmonPrintf("GlobalState RDP cmds (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + *datp || *(datp+1); + datp+=2) { + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + } + +/* + * Dump state + */ + addr = UNSEG_ADDR(gtlistp->obj.statep); + statep = (gtState *) addr; +/*rmonPrintf("======= DUMP State (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + (u8 *) datp < (u8 *) addr + sizeof(gtState); + datp++) { + PRINTF("+%08x\n",*datp); + } + if (statep->sp.rdpCmds) { + addr = UNSEG_ADDR(statep->sp.rdpCmds); +/*rmonPrintf("DUMP State RDP cmds (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + *datp || *(datp+1); + datp+=2) { + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + +/* + * Dump vertices + */ + if (gtlistp->obj.vtxp) { + addr = UNSEG_ADDR(gtlistp->obj.vtxp); +/*rmonPrintf("======= DUMP VTX (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = (u32 *) addr; + (u8 *) datp < (u8 *) addr + + (statep->sp.vtxCount * sizeof(Vtx)); + datp++) { + PRINTF("+%08x\n",*datp); + } + } + +/* + * Dump triangles + */ + if (gtlistp->obj.trip) { + addr = UNSEG_ADDR(gtlistp->obj.trip); +/*rmonPrintf("======= DUMP TRI (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = (u32 *) addr; + (u8 *) datp < (u8 *) addr + + (statep->sp.triCount * sizeof(gtTriN)); + datp++) { + PRINTF("+%08x\n",*datp); + } + } + + + + gtlistp++; + } + + +/* + * Dump Last global state + */ + if (gtlistp->obj.gstatep) { + addr = UNSEG_ADDR(gtlistp->obj.gstatep); + globp = (gtGlobState *) addr; +/*rmonPrintf("======= DUMP GlobalState (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + (u8 *) datp < (u8 *) addr + sizeof(gtGlobState); + datp++) { + PRINTF("+%08x\n",*datp); + } + if (globp->sp.rdpCmds) { + addr = UNSEG_ADDR(globp->sp.rdpCmds); +/*rmonPrintf("GlobalState RDP cmds (%x)\n",(int)addr);*/ + PRINTF("& %08x\n",PHYS(addr)); + for (datp = addr; + *datp || *(datp+1); + datp+=2) { + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + PRINTF("+%08x\n",*datp); + PRINTF("+%08x\n",*(datp+1)); + } + } + + PRINTF("^\nGBI_DUMP_END:\n"); + + + if (flags & GT_DUMPTURBO_HANGAFTER) { + for (i=0; i<1000;i++) + rmonPrintf("=======================================\n"); + while(1); + } + + +/* + * Dumps stuff + * each line is either an address for data to follow or data itself + * 1st char on line indicates what it is: + * + * $ task header address + * @ display list address + * & dma data address + * % texture address + * ? code/code data address + * + * < task header data + * > 1st half of display list command + * - 2nd half of display list command + * + dma data + * * texture data + * | code/code data + * + */ + +} diff --git a/lib/ultralib/src/gt/gt.c b/lib/ultralib/src/gt/gt.c new file mode 100644 index 0000000..bf99e85 --- /dev/null +++ b/lib/ultralib/src/gt/gt.c @@ -0,0 +1,155 @@ + +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + * + */ + +/* + * File: gt.c + * Creator: hsa@sgi.com + * Create Date: Fri Oct 13 14:23:48 PDT 1995 + * + */ + + +#include "gtint.h" + + +/* + * Set the cached RDP othermode word in the gt state structure. + */ +void +gtStateSetOthermode(Gfx *om, gtStateOthermode_t mode, int data) +{ + int shift, length; + u32 mask; + + if (mode == GT_CLEAR) { /* special case */ + om->words.w0 = (G_RDPSETOTHERMODE << 24); + om->words.w1 = 0x0; + } + + if (mode <= GT_RENDERMODE) { + /* these are OTHERMODE_L */ + switch (mode) { + + case GT_ALPHACOMPARE: + shift = G_MDSFT_ALPHACOMPARE; + length = 2; + break; + + case GT_ZSRCSEL: + shift = G_MDSFT_ZSRCSEL; + length = 1; + break; + + case GT_RENDERMODE: + shift = G_MDSFT_RENDERMODE; + length = 29; + break; + + default: + break; + } + + mask = (0x01 << length); + mask = mask - 1; + mask = (mask << shift); + mask = mask ^ 0xffffffff; + om->words.w1 &= mask; + om->words.w1 |= data; + + } else { + /* these are OTHERMODE_H */ + switch (mode) { + case GT_ALPHADITHER: + shift = G_MDSFT_ALPHADITHER; + length = 2; + break; + + case GT_RGBDITHER: + shift = G_MDSFT_RGBDITHER; + length = 2; + break; + + case GT_COMBKEY: + shift = G_MDSFT_COMBKEY; + length = 1; + break; + + case GT_TEXTCONV: + shift = G_MDSFT_TEXTCONV; + length = 3; + break; + + case GT_TEXTFILT: + shift = G_MDSFT_TEXTFILT; + length = 2; + break; + + case GT_TEXTLUT: + shift = G_MDSFT_TEXTLUT; + length = 2; + break; + + case GT_TEXTLOD: + shift = G_MDSFT_TEXTLOD; + length = 1; + break; + + case GT_TEXTDETAIL: + shift = G_MDSFT_TEXTDETAIL; + length = 2; + break; + + case GT_TEXTPERSP: + shift = G_MDSFT_TEXTPERSP; + length = 1; + break; + + case GT_CYCLETYPE: + shift = G_MDSFT_CYCLETYPE; + length = 2; + break; + + case GT_PIPELINE: + shift = G_MDSFT_PIPELINE; + length = 1; + break; + + default: + break; + } + + mask = (0x01 << length); + mask = mask - 1; + mask = (mask << shift); + mask = mask ^ 0xffffffff; + om->words.w0 &= mask; + om->words.w0 |= data; + } + + /* force cached othermode word to have proper command id: */ + om->words.w0 &= 0x00ffffff; + om->words.w0 |= (G_RDPSETOTHERMODE << 24); +} + diff --git a/lib/ultralib/src/gt/gtint.h b/lib/ultralib/src/gt/gtint.h new file mode 100644 index 0000000..31ddd7c --- /dev/null +++ b/lib/ultralib/src/gt/gtint.h @@ -0,0 +1,36 @@ + +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + * + */ + +/* + * File: gtint.h + * Creator: hsa@sgi.com + * Create Date: Fri Oct 13 14:24:36 PDT 1995 + * + */ + +#include "mbi.h" +#include "gu.h" +#include "gt.h" + diff --git a/lib/ultralib/src/gu/Makefile b/lib/ultralib/src/gu/Makefile new file mode 100644 index 0000000..ad6e2fa --- /dev/null +++ b/lib/ultralib/src/gu/Makefile @@ -0,0 +1,52 @@ +#!smake +# +# Makefile for the gu subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + + +# LCOPTS = -mips2 -non_shared -fullwarn -G 0 +LCINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include +LCOPTS = -G 0 -g -O + +CFILES = \ + align.c \ + cosf.c \ + coss.c \ + frustum.c \ + guloadtile_bug.c \ + loadtextureblockmipmap.c\ + lookat.c \ + lookathil.c \ + lookatref.c \ + lookatstereo.c \ + mtxcatf.c \ + mtxcatl.c \ + mtxutil.c \ + normalize.c \ + ortho.c \ + perspective.c \ + position.c \ + poslight.c \ + poslighthil.c \ + random.c \ + rotate.c \ + rotaterpy.c \ + scale.c \ + sinf.c \ + sins.c \ + translate.c \ + us2dex.c \ + us2dex_emu.c \ + us2dex2_emu.c \ + usprite.c + +ASFILES = \ + libm_vals.s \ + sqrtf.s +OBJECTS = $(CFILES:.c=.o) + +default: $(OBJECTS) + +include $(COMMONRULES) diff --git a/lib/ultralib/src/gu/align.c b/lib/ultralib/src/gu/align.c new file mode 100644 index 0000000..9be7b4a --- /dev/null +++ b/lib/ultralib/src/gu/align.c @@ -0,0 +1,75 @@ +/************************************************************************** + * * + * 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" + +/* + * S = sin (a) + * C = cos (a) + * H = sqrt (X*X + Z*Z) + * + * [ v ] [ C S ] [ 1 ] [ -Z/H X/H ] + * [ -S C ] [ H Y ] [ 1 ] + * [ 1 ] [ -Y H ] [ -X/H -Z/H ] + * [ 1 ] [ 1 ] [ 1 ] + * + */ + +void guAlignF(float mf[4][4], float a, float x, float y, float z) +{ + static float dtor = 3.1415926 / 180.0; + float s, c, h, hinv; + + guNormalize(&x, &y, &z); + + a *= dtor; + s = sinf (a); + c = cosf (a); + h = sqrtf (x*x + z*z); + + guMtxIdentF(mf); + + if (h != 0) { + hinv = 1 / h; + + mf[0][0] = (-z*c - s*y*x) * hinv; + mf[1][0] = (z*s - c*y*x) * hinv; + mf[2][0] = -x; + mf[3][0] = 0; + + mf[0][1] = s*h; + mf[1][1] = c*h; + mf[2][1] = -y; + mf[3][1] = 0; + + mf[0][2] = (c*x - s*y*z) * hinv; + mf[1][2] = (-s*x - c*y*z) * hinv; + mf[2][2] = -z; + mf[3][2] = 0; + + mf[0][3] = 0; + mf[1][3] = 0; + mf[2][3] = 0; + mf[3][3] = 1; + } else { + /* XXX: should do this right */ + } +} + +void guAlign(Mtx *m, float a, float x, float y, float z) +{ + Matrix mf; + + guAlignF(mf, a, x, y, z); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/cosf.c b/lib/ultralib/src/gu/cosf.c new file mode 100644 index 0000000..5a66c1b --- /dev/null +++ b/lib/ultralib/src/gu/cosf.c @@ -0,0 +1,137 @@ +/************************************************************************** + * * + * 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: fcos.c + * $Revision: 1.3 $ + * $Date: 1998/10/09 06:10:53 $ + * $Author: has $ + * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/libultra/monegi/gu/cosf.c,v $ + * + * Revision history: + * 09-Jun-93 - Original Version + * + * Description: source code for fcos function + * + * ==================================================================== + * ==================================================================== + */ + +#pragma weak fcos = __cosf +#pragma weak cosf = __cosf +#define fcos __cosf + +/* coefficients for polynomial approximation of cos 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 fcos + * + * Description computes cosine of arg + * + * ==================================================================== + */ + +float +fcos( float x ) +{ +float absx; +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 < 0x136 ) + { + /* |x| < 2^28 */ + + /* use the standard algorithm from Cody and Waite, doing + the computations in double precision + */ + + absx = ABS(x); + + dx = absx; + + dn = dx*rpi.d + 0.5; + n = ROUND(dn); + dn = n; + + dn -= 0.5; + + dx = dx - dn*pihi.d; + dx = dx - dn*pilo.d; /* dx = x - (n - 0.5)*pi */ + + xsq = dx*dx; + + poly = ((P[4].d*xsq + P[3].d)*xsq + P[2].d)*xsq + P[1].d; + + result = dx + (dx*xsq)*poly; + + /* negate result if n is odd */ + + 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 ); +} diff --git a/lib/ultralib/src/gu/coss.c b/lib/ultralib/src/gu/coss.c new file mode 100644 index 0000000..0d95530 --- /dev/null +++ b/lib/ultralib/src/gu/coss.c @@ -0,0 +1,45 @@ +/************************************************************************** + * * + * 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: coss.c + * $Revision: 1.3 $ + * $Date: 1998/10/09 06:11:01 $ + * $Author: has $ + * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/libultra/monegi/gu/coss.c,v $ + * + * ==================================================================== + * ==================================================================== + */ + +/* coefficients for polynomial approximation of sin on +/- pi/2 */ + +/* ==================================================================== + * + * FunctionName coss + * + * Description computes cosine of arg + * + * ==================================================================== + */ + +signed short +coss( unsigned short x ) +{ + /* 0 <= x < 0x10000 ==> 0 <= x < 2PI */ + + return sins ((unsigned short) (x + 0x4000)); +} diff --git a/lib/ultralib/src/gu/dump_gbi.c b/lib/ultralib/src/gu/dump_gbi.c new file mode 100644 index 0000000..a5e5e12 --- /dev/null +++ b/lib/ultralib/src/gu/dump_gbi.c @@ -0,0 +1,274 @@ + +/************************************************************************** + * * + * 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. * + * * + *************************************************************************/ + +/* + * Interpret Task with GBI display list and dump it for debugging. + */ + + +/************************************************** + * + * guDumpGbiDL no longer supported + * applications should use guParseGbiDL with the + * GU_PARSEGBI_DUMPONLY flag set. + * + **************************************************/ + + +#if 0 + + +#include "ultra64.h" +#include "bstring.h" + +#undef PRINTF +#define PRINTF osSyncPrintf + +#define DL_STACKSIZE 11 +static u32 *Gp[DL_STACKSIZE]; + +#define TX_MAX 100 +static u32 textures[TX_MAX]; +static u32 numtextures; + +static u32 segment_base[16]; +static u32 dotextures = TRUE; +static int dl_depth = 0; + + +/* + * dump a DMA-type display list command. + */ +static void +dump_dma(u32 *bufp) +{ + u32 addr, + *data; + u8 seg_id; + u16 len; + char op, + b0; + + op = ((*bufp & 0xff000000) >> 24); + + /* + * DMA op addressing is all the same: + */ + seg_id = (u8) ((bufp[1] & 0x0f000000) >> 24); + addr = segment_base[seg_id] + (bufp[1] & 0x00ffffff); + + + addr = (u32) osPhysicalToVirtual(addr); + + len = (u16) (bufp[0] & 0x0000ffff); + + PRINTF(">%08x\n-%08x\n", bufp[0], bufp[1]); + if (op == (char) G_DL) { + b0 = (char) ((bufp[0] & 0x00ff0000) >> 16); + ++dl_depth; + if (dl_depth > (DL_STACKSIZE - 1)) { + PRINTF("***** Error, max levels of display lists exceeded\n"); + return; + } + Gp[dl_depth] = (u32 *) addr; + PRINTF("@ %08x\n",(int)Gp[dl_depth]&0x7fffffff); + } else { + PRINTF("& %08x\n", (int)addr&0x7fffffff); + data = (u32 *) addr; + while(len>0) { + PRINTF("+%08x\n", *data); + data++; + len -= 4; + } + PRINTF("@ %08x\n",(int)(Gp[dl_depth] + (sizeof(Gfx) >> 2))&0x7fffffff); + } +} + +/* + * dump a IMM-type display list command. + */ +static void +dump_imm(u32 *bufp) +{ + char op, + b0; + + op = ((*bufp & 0xff000000) >> 24); + + PRINTF(">%08x\n-%08x\n", bufp[0], bufp[1]); + if (op == (char) G_ENDDL) { + dl_depth--; + if (dl_depth >= 0) { + PRINTF("@ %08x\n",(int)(Gp[dl_depth] + (sizeof(Gfx) >> 2))&0x7fffffff); + } + } + if (op == (char) G_MOVEWORD) { + if (((bufp[0] ) & 0xff) == G_MW_SEGMENT) { + b0 = (char) ((bufp[0] & 0xff00)>>10); + segment_base[b0] = bufp[1] & 0x00ffffff; + } + } +} + +/* + * dump a RDP-type display list command. + */ +static void +dump_rdp(u32 *bufp) +{ + u8 seg_id; + u32 addr; + int i0, + i1; + char op; + + op = ((*bufp & 0xff000000) >> 24); + + PRINTF(">%08x\n-%08x\n", bufp[0], bufp[1]); + if (op == (char) G_SETTIMG && dotextures) { + if (numtextures>=TX_MAX) { + PRINTF("GBI DUMP ERROR: too many textures (max=%d)\n",TX_MAX); + return; + } + seg_id = (u8) ((bufp[1] & 0x0f000000) >> 24); + addr = segment_base[seg_id] + (bufp[1] & 0x00ffffff); + addr = (u32) osPhysicalToVirtual(addr); + i1=1; + for (i0=0;i0<numtextures;i0++) + if (textures[i0] == addr) i1=0; + if (i1) textures[numtextures++]=addr; + } +} + +/* + * Takes a pointer in DRAM, and a length in bytes. Dumps + * the display list, until a G_ENDDL command is found. + */ +static void +guDumpGbi(u32 *gfxp) +{ + u8 op; + u32 readBuf[4]; + + Gp[dl_depth] = gfxp; + numtextures=0; + + PRINTF("@ %08x\n",(int)Gp[dl_depth]&0x7fffffff); + + while ((dl_depth >= 0) && (dl_depth < (DL_STACKSIZE - 1))) { + + op = (u8) ((*Gp[dl_depth] & 0xff000000) >> 24); + bcopy((char *) Gp[dl_depth], (char *) &(readBuf[0]), sizeof(Gfx)); + + switch (op & 0xc0) { + + case (u8) 0x00: + dump_dma(readBuf); + break; + + case (u8) 0x80: + dump_imm(readBuf); + break; + + case (u8) 0xc0: + dump_rdp(readBuf); + break; + + default: + PRINTF("ERROR : display list is lost, op = %02x\n", op); + break; + + } + + if (op != (u8) G_DL) { + Gp[dl_depth] += (sizeof(Gfx) >> 2); + } + } + if (dotextures) { + u32 i,j; + for (i=0; i<numtextures; i++) { + PRINTF("%% %08x\n",textures[i]&0x7fffffff); + for (j=textures[i]; j<textures[i]+0x400; j+=4) { + PRINTF("*%08x\n",(int) *((u32 *) j)); + } + } + } +} + +#define UCODE_SIZE_MAX (4096*3) +void +guDumpGbiDL(OSTask *tp,u8 flags) +{ + int i; + + if (flags & GU_PARSEGBI_NOTEXTURES) dotextures=0; + + PRINTF("\nGBI_DUMP_START:\n"); + PRINTF("$ %08x\n",(int) tp & 0x7fffffff); + + for (i=(int)tp; i<(int)tp+sizeof(OSTask); i+=4) { + PRINTF("<%08x\n",(int) *((u32 *) i)); + } + + PRINTF("? %08x\n",(int) tp->t.ucode_boot & 0x7fffffff); + for (i=(int)tp->t.ucode_boot; i<(int)tp->t.ucode_boot+tp->t.ucode_boot_size; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + + PRINTF("? %08x\n",(int) tp->t.ucode& 0x7fffffff); + for (i=(int)tp->t.ucode; i<(int)tp->t.ucode+UCODE_SIZE_MAX; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + + PRINTF("? %08x\n",(int) tp->t.ucode_data & 0x7fffffff); + for (i=(int)tp->t.ucode_data; i<(int)tp->t.ucode_data+tp->t.ucode_data_size; i+=4) { + PRINTF("|%08x\n",(int) *((u32 *) i)); + } + + + guDumpGbi((u32 *) tp->t.data_ptr); + + + PRINTF("^\nGBI_DUMP_END:\n"); + + if (flags & GU_PARSEGBI_HANGAFTER) { + int i; + for (i=0; i<1000;i++) + PRINTF("=============================================================\n"); + while(1); + } + + +/* + * Dumps stuff + * each line is either an address for data to follow or data itself + * 1st char on line indicates what it is: + * + * $ task header address + * @ display list address + * & dma data address + * % texture address + * ? code/code data address + * + * < task header data + * > 1st half of display list command + * - 2nd half of display list command + * + dma data + * * texture data + * | code/code data + * + */ + +} + +#endif diff --git a/lib/ultralib/src/gu/frustum.c b/lib/ultralib/src/gu/frustum.c new file mode 100644 index 0000000..4af9c5d --- /dev/null +++ b/lib/ultralib/src/gu/frustum.c @@ -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 "guint.h" + +void guFrustumF(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*n/(r-l); + mf[1][1] = 2*n/(t-b); + mf[2][0] = (r+l)/(r-l); + mf[2][1] = (t+b)/(t-b); + mf[2][2] = -(f+n)/(f-n); + mf[2][3] = -1; + mf[3][2] = -2*f*n/(f-n); + mf[3][3] = 0; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + mf[i][j] *= scale; +} + +void guFrustum(Mtx *m, float l, float r, float b, float t, float n, float f, float scale) +{ + Matrix mf; + + guFrustumF(mf, l, r, b, t, n, f, scale); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/guint.h b/lib/ultralib/src/gu/guint.h new file mode 100644 index 0000000..c3206dd --- /dev/null +++ b/lib/ultralib/src/gu/guint.h @@ -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; diff --git a/lib/ultralib/src/gu/guloadtile_bug.c b/lib/ultralib/src/gu/guloadtile_bug.c new file mode 100644 index 0000000..e16e250 --- /dev/null +++ b/lib/ultralib/src/gu/guloadtile_bug.c @@ -0,0 +1,235 @@ +/************************************************************************** + * * + * 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 "ultra64.h" + +/* + * Inidicates how many words will be added to display list + * by guDPLoadTextureTile function. + */ +int +guGetDPLoadTextureTileSz(int ult, int lrt) +{ + return (((lrt - ult + 1) / 2) * 4 + 3); +} + +/* + * Workaround for load_tile bug on tapeout one hardware. Uses + * load blocks for each line. ~25% more dma traffic + memory for + * extra commands. + */ +void +guDPLoadTextureTile(Gfx * temp, void *timg, + int texl_fmt, int texl_size, + int img_width, int img_height, + int uls, int ult, int lrs, int lrt, + int palette, + int cms, int cmt, + int masks, int maskt, + int shifts, int shiftt) +{ + int line; + int tile_width, + tile_height; /* + + * in texels + */ + int dxt; + int sizeb; + int lineb; + int line_size; /* + + * in 64-bit words + */ + int texel_num_pad; /* + + * in texels, pad to 64-bit word size + */ + int count; + int tmem; + int tile; + int s, + t; + + tile_width = lrs - uls + 1; + tile_height = lrt - ult + 1; + + switch (texl_size) { + case G_IM_SIZ_8b: + sizeb = G_IM_SIZ_8b_BYTES; + lineb = G_IM_SIZ_8b_LINE_BYTES; + break; + case G_IM_SIZ_16b: + sizeb = G_IM_SIZ_16b_BYTES; + lineb = G_IM_SIZ_16b_LINE_BYTES; + break; + case G_IM_SIZ_32b: + sizeb = G_IM_SIZ_32b_BYTES; + lineb = G_IM_SIZ_32b_LINE_BYTES; + break; + } + + dxt = CALC_DXT(tile_width, sizeb); + line_size = ((tile_width * lineb) + 7) >> 3; + /* + * pad line to word boundary + */ + texel_num_pad = ((((tile_width * sizeb) + 7) >> 3) * 8) / sizeb; + + gDPSetTextureImage(temp++, texl_fmt, texl_size, img_width, timg); + + for (line = 0; line < tile_height; line += 2) { + t = (ult + line) & ~1; /* + * load from even line + */ + tmem = line * line_size; + + /* + * set for both loads, avoid sync by alternating tiles + */ + tile = (line % 4) ? 1 : 0; + + gDPSetTile(temp++, texl_fmt, texl_size, 0, tmem, G_TX_LOADTILE - tile, 0, + cmt, maskt, shiftt, + cms, masks, shifts); + + /* + * do odd line first + */ + s = uls + img_width - texel_num_pad; + count = (texel_num_pad * 2) - 1; + + gDPLoadBlock(temp++, G_TX_LOADTILE - tile, s, t, s + count, dxt); + + /* + * do even line + */ + s = uls; + count = tile_width - 1; + + gDPLoadSync(temp++); + gDPLoadBlock(temp++, G_TX_LOADTILE - tile, s, t, s + count, dxt); + + } + + /* + * set final tile + */ + gDPSetTile(temp++, texl_fmt, texl_size, line_size, 0, G_TX_RENDERTILE, 0, + cmt, maskt, shiftt, + cms, masks, shifts); + + gDPSetTileSize(temp++, G_TX_RENDERTILE, + (uls) << G_TEXTURE_IMAGE_FRAC, + (ult) << G_TEXTURE_IMAGE_FRAC, + (lrs) << G_TEXTURE_IMAGE_FRAC, + (lrt) << G_TEXTURE_IMAGE_FRAC); +} + +/* + * 4-BIT VERSION + */ + +/* + * Inidicates how many words will be added to display list + * by guDPLoadTextureTile function. + */ +int +guGetDPLoadTextureTile_4bSz(int ult, int lrt) +{ + return (((lrt - ult + 1) / 2) * 4 + 3); +} + +/* + * Workaround for load_tile bug on version 1.0 hardware. Uses + * load blocks for each line. ~25% more dma traffic + memory for + * extra commands. + */ +void +guDPLoadTextureTile_4b(Gfx * temp, void *timg, + int texl_fmt, + int img_width, int img_height, + int uls, int ult, int lrs, int lrt, + int palette, + int cms, int cmt, + int masks, int maskt, + int shifts, int shiftt) +{ + int line; + int tile_width, + tile_height; + int dxt; + int sizeb; + int lineb; + int line_size; + int count; + int tmem; + int tile; + int s, + t; + + tile_width = (lrs - uls + 1) >> 1; + tile_height = lrt - ult + 1; + sizeb = G_IM_SIZ_8b_BYTES; + lineb = G_IM_SIZ_8b_LINE_BYTES; + line_size = ((tile_width * lineb) + 7) >> 3; + dxt = CALC_DXT_4b(tile_width); + + gDPSetTextureImage(temp++, texl_fmt, G_IM_SIZ_8b, ((img_width) >> 1), timg); + + for (line = 0; line < tile_height; line += 2) { + t = (ult + line) & ~1; /* + * load from even line + */ + tmem = line * line_size; + + /* + * set for both loads, avoid sync by alternating tiles + */ + tile = (line % 4) ? 1 : 0; + + gDPSetTile(temp++, texl_fmt, G_IM_SIZ_8b, 0, tmem, G_TX_LOADTILE - tile, 0, + cmt, maskt, shiftt, + cms, masks, shifts); + + /* + * do odd line first + */ + s = uls + img_width - line_size * 8; + count = (line_size * 8 * 2) - 1; + + gDPLoadBlock(temp++, G_TX_LOADTILE - tile, s, t, s + count, dxt); + + /* + * do even line + */ + s = uls; + count = tile_width - 1; + + gDPLoadSync(temp++); + gDPLoadBlock(temp++, G_TX_LOADTILE - tile, s, t, s + count, dxt); + + } + + /* + * set final tile + */ + gDPSetTile(temp++, texl_fmt, G_IM_SIZ_4b, line_size, 0, G_TX_RENDERTILE, 0, + cmt, maskt, shiftt, + cms, masks, shifts); + + gDPSetTileSize(temp++, G_TX_RENDERTILE, + (uls) << G_TEXTURE_IMAGE_FRAC, + (ult) << G_TEXTURE_IMAGE_FRAC, + (lrs) << G_TEXTURE_IMAGE_FRAC, + (lrt) << G_TEXTURE_IMAGE_FRAC); +} diff --git a/lib/ultralib/src/gu/libm_vals.s b/lib/ultralib/src/gu/libm_vals.s new file mode 100644 index 0000000..b88ad98 --- /dev/null +++ b/lib/ultralib/src/gu/libm_vals.s @@ -0,0 +1,5 @@ + .rdata + .align 4 + .globl __libm_qnan_f +__libm_qnan_f: + .word 0x7F810000 diff --git a/lib/ultralib/src/gu/loadtextureblockmipmap.c b/lib/ultralib/src/gu/loadtextureblockmipmap.c new file mode 100644 index 0000000..786f64a --- /dev/null +++ b/lib/ultralib/src/gu/loadtextureblockmipmap.c @@ -0,0 +1,716 @@ +/************************************************************************** + * * + * 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. * + * * + **************************************************************************/ + +/**************************************************************************** + * NOTE: To view this file correctly, set tabstop=3 +*****************************************************************************/ +#include "guint.h" +#include <stdio.h> +#include "ultra64.h" + +// TODO: this comes from a header +#ident "$Revision: 1.49 $" + +#define TRAM_SIZE 4096 /* in bytes */ +#define TRAM_WSIZE 8 /* TRAM word size in bytes */ +#define TRAM_LSIZE 8 /* TRAM load word size in bytes */ +#define MM_MAX_LEVEL 7 /* number of mipmap levels 0 to MM_MAX_LEVEL */ +#define MM_MIN_SIZE 1 /* smallest mipmap tile */ + +struct texelSizeParams +{ + unsigned char gran; + unsigned char shift; + unsigned char tsize; + unsigned char shiftr; +}; + +/* texture ram tile */ +struct Tile +{ + int w; /* width of tile in texels, padded to tram line sz */ + int s, t; /* size of tile in texels */ + int addr; /* address in tram of tile */ +}; + +/* tram mipmaps */ +static struct Tile mipmap[MM_MAX_LEVEL+1]; +static struct texelSizeParams sizeParams[4] = + { 16, 3, 1, 0, + 8, 2, 2, 1, + 4, 1, 4, 2, + 2, 0, 8, 3 + }; + + +static int max_mipmap; +static unsigned char *tram; +static int txlsize; +static int errNo = 0; +static int NA = 0; /* Not applicable */ +static unsigned int length; /* total texels in mipmap */ +static int level; /* total levels in mipmap */ + +static void get3x3(struct Tile *tile, int *s, int *t, int *texel, int shift, int size); +static void stuffDisplayList(Gfx **glistp, Image *im, char *tbuf, unsigned char startTile, + unsigned char pal, unsigned char cms, unsigned char cmt, + unsigned char masks, unsigned char maskt, unsigned char shifts, + unsigned char shiftt); +static void kernel(int i, int r1, int g1, int b1, int a1, float *r2, float *g2, + float *b2, float *a2); + +#define unpack_ia16(c,i,a) \ + i = (c & 0xff00) >> 8, a = (c & 0xff) +#define pack_ia16(i,a) \ + (i << 8) | a + +#define unpack_ia8(c,i,a) \ + i = ((c & 0xf0) >> 4), a = (c & 0xf) +#define pack_ia8(i,a) \ + (a & 0xf) | ((i & 0xf) << 4) + +#define unpack_ia4(c,i,a) \ + i = ((c & 0xe) >> 1), a = (c & 0x1) +#define pack_ia4(i,a) \ + ((i & 0x7) << 1) | ((a & 0x1)) + +#define unpack_i4(c,i) \ + i = (c & 0xf) +#define pack_i4(i) \ + (i) + +#define unpack_i8(c,i) \ + i = (c & 0xff) +#define pack_i8(i) \ + (i) + +#define unpack_ci8(c,ci) unpack_i8(c,ci) +#define pack_ci8(ci) pack_i8(ci) + +#define unpack_ci4(c,ci) unpack_i4(c,ci) +#define pack_ci4(ci) pack_i4(ci) + +#define unpack_rgba(c,r,g,b,a) \ + (r = (c & 0xf800) >> 11), g = ((c & 0x07c0) >> 6), b = ((c & 0x003e) >> 1), \ + a = (c & 0x1) + +#define pack_rgba( r, g, b, a) ((r&0x1f) << 11) | (g&0x1f) << 6 | \ + ((b&0x1f) << 1) | (a) + +/************************************************************************* + * Generates all levels of a power-of-two mipmap from an input array. * + * Also stuffs display list with entries for loading and rendering the * + * texture. Filtering Color-Index maps makes sense only if the lookup * + * is a linear ramp. Billboards and trees cutout using alpha will change * + * shape as the level changes due to change in map resolution. Texel * + * formats with only one bit of alpha will not be filtered very well. * + ************************************************************************* + * ErrNo value error description * + *-----------------------------------------------------------------------* + * 1 Mipmap too big to load into tmem. Not Fatal, * + * will load as many levels as there is space for. * + * * + * 2 Texel format not supported, Fatal error * + ************************************************************************/ + +int guLoadTextureBlockMipMap(Gfx **glistp, unsigned char *tbuf, Image *im, + unsigned char startTile, unsigned char pal, unsigned char cms, unsigned char cmt, + unsigned char masks, unsigned char maskt, unsigned char shifts, unsigned char shiftt, + unsigned char cfs, unsigned char cft) +{ + + unsigned char *iaddr, *taddr; + int im_bytes, tr_bytes; + int h, b; + int flip; + char startUnAligned; + char endUnAligned; + + txlsize = sizeParams[im->siz].tsize; /* texel size in nibbles */ + /* to next line size */ + + /* + * Do top level map, swizzle bytes on odd t's * + */ + /* base char address of tile to be loaded */ + iaddr = ((im->t * im->lsize)+((im->s * txlsize) >> 1) + im->base); + + /*check tile line starting and ending alignments along 4bit bndries */ + startUnAligned = ((im->s & 0x1) && (im->siz == G_IM_SIZ_4b)); + endUnAligned = (((im->s + im->w) & 0x1) && (im->siz == G_IM_SIZ_4b)); + + im_bytes = ((im->w * txlsize + 1) >> 1); /* siz of 1 tile line in bytes */ + tr_bytes = im_bytes / TRAM_LSIZE; /* no of tram lines per tile line */ + tr_bytes = tr_bytes * TRAM_LSIZE; /* tile line size in bytes */ + if (im_bytes > tr_bytes) tr_bytes += TRAM_LSIZE; + + taddr = &tbuf[im->addr]; /* why ? make this zero?*/ + + if (startUnAligned) + { + for (h=0; h<im->h; h++) + { + flip = (h & 1) << 2; /*shift does not depend on txlsize*/ + for (b=0; b<im_bytes; b++) + { + *(taddr+(b^flip)) = ((*(iaddr+b) & 0x0f) << 4) + | ((*(iaddr+b+1) & 0xf0) >> 4); + } + /* add last aligned nibble */ + if (!endUnAligned) *(taddr+((b-1)^flip)) &= (0xf0); + /* pickup trailing bytes */ + for (b=im_bytes; b<tr_bytes; b++) *(taddr+(b^flip)) = 0; + iaddr += im->lsize; + taddr += tr_bytes; + } + } + else /* if start aligned */ + { + for (h=0; h<im->h; h++) + { + flip = (h & 1) << 2; /*shift does not depend on txlsize*/ + for (b=0; b<im_bytes; b++) + *(taddr+(b^flip)) = *(iaddr+b); + + /* zero out last extra nibble */ + if (endUnAligned) *(taddr+((b-1)^flip)) &= (0xf0); + /* pad trailing bytes with zeroes */ + for (b=im_bytes; b<tr_bytes; b++) *(taddr+(b^flip)) = 0; + + iaddr += im->lsize; + taddr += tr_bytes; + } + } + + tram = tbuf; + + /* save tile attributes in top mipmap */ + mipmap[0].s = im->w; /* tile width */ + mipmap[0].t = im->h; /* tile height */ + /* guaranteed no remainder ? */ + mipmap[0].w = ((tr_bytes / txlsize) << 1); /* tile line width in texels*/ + mipmap[0].addr = im->addr; + max_mipmap = MM_MAX_LEVEL; + length = mipmap[0].w*mipmap[0].t; /* total texels in level 0 */ +/** + rmonPrintf("level0 w,t,l = %d %d %d\n",mipmap[0].w, mipmap[0].t,length); +***/ + +/****************************************************************************** + Generate other levels of mipmap using a box filter +******************************************************************************/ + +{/* generate mip map for this tile */ + unsigned char *taddr, *saddr; + int shift = (int) sizeParams[im->siz].shift; + int s, t, si, ti, sii, tii; + int s4[9]; + int t4[9]; + int tex4[9]; + int r0, g0, b0, a0, r1, g1, b1, a1; + float r2 ,g2, b2, a2; + float dummy; + int i0, ci0, ia0, i1, ci1, ia1; + float i2, ci2, ia2; + int texel; + int i,trip; + unsigned int tempaddr; + int ntexels = ((TRAM_LSIZE/txlsize) << 1); /* texels per line */ + + level = 0; /* need to check for memory overflow */ + while ((mipmap[level].s > 1) || (mipmap[level].t > 1)) + { + level++; + /* + * set new mipmap level address in bytes + */ + mipmap[level].addr = mipmap[level-1].addr + + (mipmap[level-1].w * txlsize * mipmap[level-1].t >> 1); + + /* + * grab location in tram pointing to the current level address + */ + taddr = &(tram[ mipmap[level].addr ]); + + /* + * downfilter by 2X, bump odd size + * compute parameters for new mipmap level + */ + mipmap[level].s = (mipmap[0].s) >> level; + mipmap[level].t = (mipmap[0].t) >> level; + + if (mipmap[level].s == 0) mipmap[level].s = 1; + if (mipmap[level].t == 0) mipmap[level].t = 1; + + /* + * width must be a multiple of 8 bytes (padding for tram line size) + */ + mipmap[level].w = + ((mipmap[level].s + (ntexels -1)) >> (shift +1) << (shift +1)); + + /* + * compute total no of texels to be loaded + */ + length += mipmap[level].w*mipmap[level].t; +/** + rmonPrintf("level, w,t,l = %d %d %d %d\n", level, mipmap[level].w, mipmap[level].t,length); +**/ + if ((length*txlsize >> 1) >= TRAM_SIZE) + { + errNo = 1; + length -= mipmap[level].w*mipmap[level].t; + break; + } + + /* + * for each scanline + */ + for (t=0; t<mipmap[level-1].t; t+=2) + { + flip = 0; + trip = (t & 2) << 1; /* invert bit 4 on odd line */ + ti = t + 1; + tii = t - 1; + + /* + * check filtering clamp/wrap flag and do accordingly + */ + if ( cft) { + if (ti >= mipmap[level-1].t) ti = t; + if (tii < 0) tii = t; + } else { + if (ti >= mipmap[level-1].t) ti = 0; + if (tii < 0) tii = mipmap[level-1].t - 1; + } + + tempaddr = 0; + + for (s=0; s<mipmap[level-1].s; s+=2) + { + si = s + 1; + sii = s - 1; + /* + * duplicate last texel for odd sizes for filtering + */ + if (cfs) { + if (si >= mipmap[level-1].s) si = s; + if (sii < 0) sii = s; + } else { + if (si >= mipmap[level-1].s) si = 0; + if (sii < 0) sii = mipmap[level-1].s - 1; + } + +/*** + if (level == 6) + rmonPrintf("sts = %d %d %d %d %d %d\n", + s, si, sii, t, ti, tii); +***/ + + /* + * grab the nine neighbours to apply kernel function + */ + s4[0] = s; t4[0] = tii; + s4[1] = si; t4[1] = tii; + s4[2] = si; t4[2] = t; + s4[3] = si; t4[3] = ti; + s4[4] = s; t4[4] = ti; + s4[5] = sii; t4[5] = ti; + s4[6] = sii; t4[6] = t; + s4[7] = sii; t4[7] = tii; + s4[8] = s; t4[8] = t; + + get3x3( &mipmap[level-1], s4, t4, tex4, shift, im->siz); + + saddr = taddr + ((tempaddr >> 1)^trip); + r1 = g1 = b1 = a1 = ci1 = i1 = 0; + r2 = g2 = b2 = a2 = ci2 = i2 = 0; + + /* + * Extract R,G and B components of the 9 texels and + * apply the filter kernel + */ + switch (im->fmt) + { + case (G_IM_FMT_RGBA): + if (im->siz == G_IM_SIZ_16b) + { + for (i=0; i< 9; i++) + { + unpack_rgba(tex4[i], r0, g0, b0, a0); + kernel(i, r0, g0, b0, a0, &r2, &g2, &b2, &a2); +/*** + if (level == 6) + rmonPrintf("r0, g0, b0, a0 = %d %d %d %d\n", + r0, g0, b0, a0); +**/ + } + r1 = (int)(r2/16.0 + 0.5); + g1 = (int)(g2/16.0 + 0.5); + b1 = (int)(b2/16.0 + 0.5); + a1 = (int)(a2/16.0 + 0.5); + } + else + { + /* + * RGBA32 is not supported + */ + errNo = 2; + return errNo; + } + break; + + case (G_IM_FMT_YUV): + errNo = 2; + return errNo; + break; + + case (G_IM_FMT_CI): + if (im->siz == G_IM_SIZ_4b) + { + for (i=0; i<9; i++) + { + unpack_ci4(tex4[i],ci0); + kernel(i, ci0, 0, 0, 0, &ci2, &dummy, &dummy, + &dummy); + } + ci1 = (int)(ci2/16.0 + 0.5); + } + else + if (im->siz == G_IM_SIZ_8b) + { + for (i=0; i<9; i++) + { + unpack_ci8(tex4[i],ci0); + kernel(i, ci0, 0, 0, 0, &ci2, &dummy, + &dummy, &dummy); + } + ci1 = (int)(ci2/16.0 + 0.5); + } + else + { + errNo=2; + return errNo; + } + break; + + case (G_IM_FMT_IA): + if (im->siz == G_IM_SIZ_4b) + { + for (i=0; i<9; i++) + { + unpack_ia4(tex4[i],i0,a0); + kernel(i, i0, a0, 0, 0, &i2, &a2, &dummy, + &dummy); + } + i1 = (int)(i2/16.0 +0.5); + a1 = (int)(a2/16.0 +0.5); + } + else if (im->siz == G_IM_SIZ_8b) + { + for (i=0; i<9; i++) + { + unpack_ia8(tex4[i],i0,a0); + kernel(i, i0, a0, 0, 0, &i2, &a2, &dummy, + &dummy); + } + i1 = (int)(i2/16.0 +0.5); + a1 = (int)(a2/16.0 +0.5); + } + else + if (im->siz == G_IM_SIZ_16b) + { + for (i=0; i<9; i++) + { + unpack_ia16(tex4[i],i0,a0); + kernel(i, i0, a0, 0, 0, &i2, &a2, &dummy, + &dummy); + } + i1 = (int)(i2/16.0 +0.5); + a1 = (int)(a2/16.0 +0.5); + } + else + { + errNo = 2; + return errNo; + } + break; + + case (G_IM_FMT_I): + if (im->siz == G_IM_SIZ_4b) + { + for (i=0; i<9; i++) + { + unpack_i4(tex4[i],i0); + kernel(i, i0, 0, 0, 0, &i2, &dummy, &dummy, + &dummy); + } + i1 = (int)(i2/16.0 + 0.5); + } + else + if (im->siz == G_IM_SIZ_8b) + { + for (i=0; i<9; i++) + { + unpack_i8(tex4[i],i0); + kernel(i, i0, 0, 0, 0, &i2, &dummy, &dummy, + &dummy); + } + i1 = (int)(i2/16.0 +0.5); + } + else + { + errNo = 2; + return errNo; + } + + default: + break; + } + + /* + * Pack fields into destination texel + */ + switch (im->fmt) + { + + case (G_IM_FMT_RGBA): + texel = pack_rgba(r1,g1,b1,a1); + *(short *)((int)saddr^flip) = texel; + break; + + case (G_IM_FMT_YUV): + break; + + case (G_IM_FMT_CI): + + if (im->siz == G_IM_SIZ_4b) + { + texel = pack_ci4(ci1); + *(char *)((int)saddr^flip) |= (s & 0x2)? + (texel): (texel << 4); + } + else + if (im->siz == G_IM_SIZ_8b) + { + texel = pack_ci8(ci1); + *(char *)((int)saddr^flip) = texel; + } + break; + + case (G_IM_FMT_IA): + if (im->siz == G_IM_SIZ_4b) + { + texel = pack_ia4(i1,a1); + *(char *)((int)saddr^flip) |= (s & 0x2)? + (texel): (texel << 4); + } + else + if (im->siz == G_IM_SIZ_8b) + { + texel = pack_ia8(i1,a1); + *(char *)((int)saddr^flip) = texel; + } + else + if (im->siz == G_IM_SIZ_16b) + { + texel = pack_ia16(i1,a1); + *(short *)((int)saddr^flip) = texel; + } + break; + + case (G_IM_FMT_I): + if (im->siz == G_IM_SIZ_4b) + { + texel = pack_i4(i1); + *(char *)((int)saddr^flip) |= (s & 0x2)? + (texel): (texel << 4); + } + else + if (im->siz == G_IM_SIZ_8b) + { + texel = pack_i8(i1); + *(char *)((int)saddr^flip) = texel; + } + break; + } + + tempaddr += txlsize; + + } /* end s */ + + taddr += ((mipmap[level].w * txlsize) >> 1); + + } /* end t */ + + if (mipmap[level].s <= MM_MIN_SIZE && + mipmap[level].t <= MM_MIN_SIZE) + { + max_mipmap = level; + break; + } + } /* end level */ + +}/* end generate mipmap */ +/* + * Add entries for texture loading and rendering in DL + */ +stuffDisplayList(glistp, im, tbuf, startTile, pal, cms, cmt, masks, maskt, shifts, shiftt); + +return errNo; +} /* end guLoadTextureBlockMipMap */ + +/****************************************************************************** + * + * Apply Kernel : + * 1 2 1 + * 2 4 1 + * 1 2 1 + ******************************************************************************/ +static void kernel(int i, int r0, int g0, int b0, int a0, float *r2, float *g2, float *b2, float *a2) +{ + if (i == 8) + { + *r2 += r0*4; *g2 += g0*4; *b2 += b0*4; *a2 += a0*4; + } else + if (i%2 == 0) + { + *r2 += r0*2; + *g2 += g0*2; + *b2 += b0*2; + *a2 += a0*2; + } else + { + *r2 += r0; + *g2 += g0; + *b2 += b0; + *a2 += a0; + } +} + +/******************************************************************** + Add entries for loading and rendering textures into the display list +*********************************************************************/ +static void stuffDisplayList(Gfx **glistp, Image *im, char *tbuf, unsigned char startTile, + unsigned char pal, unsigned char cms, unsigned char cmt, + unsigned char masks, unsigned char maskt, unsigned char shifts, + unsigned char shiftt) +{ + int tile; + int Smask, Tmask; + int Sshift, Tshift; + + /* + * set LOADTILE for loading texture + * 4-bit textures are loaded in 8-bit chunks + */ + if (im->siz == G_IM_SIZ_4b) { + gDPSetTextureImage((*glistp)++, im->fmt, G_IM_SIZ_8b, 1, + osVirtualToPhysical((unsigned short *)tbuf)); + gDPSetTile((*glistp)++, im->fmt, G_IM_SIZ_8b, NA, 0, G_TX_LOADTILE, NA, + NA, NA, NA, NA, NA, NA); + /* Wait until all primitives are done */ + gDPLoadSync((*glistp)++); + gDPLoadBlock((*glistp)++, G_TX_LOADTILE, 0, 0, length/2, 0x0); + } else { + gDPSetTextureImage((*glistp)++, im->fmt, im->siz, 1, + osVirtualToPhysical((unsigned short *)tbuf)); + gDPSetTile((*glistp)++, im->fmt, im->siz, NA, 0, G_TX_LOADTILE, NA, + NA, NA, NA, NA, NA, NA); + /* Wait until all primitives are done */ + gDPLoadSync((*glistp)++); + gDPLoadBlock((*glistp)++, G_TX_LOADTILE, 0, 0, length, 0x0); + } + + for (tile = 0; tile <= level; tile ++) + { + Tmask = maskt-tile; + if (Tmask < 0){ + Tmask = 0; + } else { + Tshift = tile; + } + + Smask = masks-tile; + if (Smask < 0){ + Smask = 0; + } else { + Sshift = tile; + } + +/*** + rmonPrintf("tile, Tmask, Tshift, Smask, Sshift %d %d %d %d %d\n", + tile, Tmask, Tshift, Smask, Sshift); + rmonPrintf("%d\n",startTile); +***/ + + + gDPSetTile((*glistp)++,im->fmt, im->siz, (mipmap[tile].w*txlsize >> 4), + (mipmap[tile].addr >> 3), tile+startTile, pal, cmt, Tmask, Tshift, cms, + Smask, Sshift); + + gDPSetTileSize((*glistp)++,tile+startTile, (0 <<G_TEXTURE_IMAGE_FRAC), + (0 <<G_TEXTURE_IMAGE_FRAC), (mipmap[tile].s-1) <<G_TEXTURE_IMAGE_FRAC, + (mipmap[tile].t-1) << G_TEXTURE_IMAGE_FRAC); + } +} + +/****************************************************************************** + Extract quad of texels for filtering. Compute bank and row addresses. +******************************************************************************/ +static void get3x3(struct Tile *tile, int *s, int *t, int *texel, int shift, int size) +{ + int i; + int bank, row; + unsigned int addr; + int overlap; + unsigned char r, g, b, a; + unsigned long tex; + struct Image *im; + unsigned int ss,tt; + + for (i=0; i< 9; i++) + { + ss = s[i]; + tt = t[i]; + /* bank and row indexing */ + bank = (((ss & (0x3 << (shift-1))) >> (shift-1)) ^ ((tt & 0x1) << 1)) << 1; + row = (((tt * tile->w + ss) * txlsize) >> 1) / TRAM_LSIZE; + addr = tile->addr + row * TRAM_WSIZE + bank; + + overlap = (i == 0) ? bank : overlap ^ bank; + + switch (size) + { + case G_IM_SIZ_4b: + texel[i] = (tram[addr + ((ss & 0x2) >> 1)] + & (0xf0 >> ((ss & 0x1) << 2))); + if (!(ss & 0x1)) texel[i] = texel[i] >> 4; + break; + + case G_IM_SIZ_8b: + texel[i] = tram[addr + (ss & 0x1)]; + break; + + case G_IM_SIZ_16b: + texel[i] = (tram[addr] << 8) | tram[addr+1]; + break; + + case G_IM_SIZ_32b: + errNo = 2; /* Format not supported */ + break; + + default: + break; + } + + } +} diff --git a/lib/ultralib/src/gu/lookat.c b/lib/ultralib/src/gu/lookat.c new file mode 100644 index 0000000..1fadc17 --- /dev/null +++ b/lib/ultralib/src/gu/lookat.c @@ -0,0 +1,83 @@ +/************************************************************************** + * * + * 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" + +void guLookAtF(float mf[4][4], float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp) +{ + float len, xLook, yLook, zLook, xRight, yRight, zRight; + + guMtxIdentF(mf); + + xLook = xAt - xEye; + yLook = yAt - yEye; + zLook = zAt - zEye; + + /* Negate because positive Z is behind us: */ + len = -1.0 / sqrtf (xLook*xLook + yLook*yLook + zLook*zLook); + xLook *= len; + yLook *= len; + zLook *= len; + + /* Right = Up x Look */ + + xRight = yUp * zLook - zUp * yLook; + yRight = zUp * xLook - xUp * zLook; + zRight = xUp * yLook - yUp * xLook; + len = 1.0 / sqrtf (xRight*xRight + yRight*yRight + zRight*zRight); + xRight *= len; + yRight *= len; + zRight *= len; + + /* Up = Look x Right */ + + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + len = 1.0 / sqrtf (xUp*xUp + yUp*yUp + zUp*zUp); + xUp *= len; + yUp *= len; + zUp *= len; + + mf[0][0] = xRight; + mf[1][0] = yRight; + mf[2][0] = zRight; + mf[3][0] = -(xEye * xRight + yEye * yRight + zEye * zRight); + + mf[0][1] = xUp; + mf[1][1] = yUp; + mf[2][1] = zUp; + mf[3][1] = -(xEye * xUp + yEye * yUp + zEye * zUp); + + mf[0][2] = xLook; + mf[1][2] = yLook; + mf[2][2] = zLook; + mf[3][2] = -(xEye * xLook + yEye * yLook + zEye * zLook); + + mf[0][3] = 0; + mf[1][3] = 0; + mf[2][3] = 0; + mf[3][3] = 1; +} + +void guLookAt (Mtx *m, float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp) +{ + Matrix mf; + + guLookAtF(mf, xEye, yEye, zEye, xAt, yAt, zAt, xUp, yUp, zUp); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/lookathil.c b/lib/ultralib/src/gu/lookathil.c new file mode 100644 index 0000000..a848688 --- /dev/null +++ b/lib/ultralib/src/gu/lookathil.c @@ -0,0 +1,185 @@ +/************************************************************************** + * * + * 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" + + +void guLookAtHiliteF(float mf[4][4], LookAt *l, Hilite *h, + float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp, + float xl1, float yl1, float zl1, /* light 1 direction */ + float xl2, float yl2, float zl2, /* light 2 direction */ + int twidth, int theight) /* highlight txtr size*/ +{ + float len, xLook, yLook, zLook, xRight, yRight, zRight; + float xHilite, yHilite, zHilite; + + guMtxIdentF(mf); + + xLook = xAt - xEye; + yLook = yAt - yEye; + zLook = zAt - zEye; + + /* Negate because positive Z is behind us: */ + len = -1.0 / sqrtf (xLook*xLook + yLook*yLook + zLook*zLook); + xLook *= len; + yLook *= len; + zLook *= len; + + /* Right = Up x Look */ + + xRight = yUp * zLook - zUp * yLook; + yRight = zUp * xLook - xUp * zLook; + zRight = xUp * yLook - yUp * xLook; + len = 1.0 / sqrtf (xRight*xRight + yRight*yRight + zRight*zRight); + xRight *= len; + yRight *= len; + zRight *= len; + + /* Up = Look x Right */ + + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + len = 1.0 / sqrtf (xUp*xUp + yUp*yUp + zUp*zUp); + xUp *= len; + yUp *= len; + zUp *= len; + + /* hilite vectors */ + + len = 1.0 / sqrtf (xl1*xl1 + yl1*yl1 + zl1*zl1); + xl1 *= len; + yl1 *= len; + zl1 *= len; + +#define THRESH2 0.1 + xHilite = xl1 + xLook; + yHilite = yl1 + yLook; + zHilite = zl1 + zLook; + + len = sqrtf (xHilite*xHilite + yHilite*yHilite + zHilite*zHilite); + + if (len>THRESH2) + { + len = 1.0 / len; + xHilite *= len; + yHilite *= len; + zHilite *= len; + + h->h.x1 = + twidth*4 + (xHilite*xRight + + yHilite*yRight + + zHilite*zRight)*twidth*2; + + h->h.y1 = + theight*4 + (xHilite*xUp + + yHilite*yUp + + zHilite*zUp)*theight*2; + } + else + { + h->h.x1 = twidth*2; + h->h.y1 = theight*2; + } + + len = 1.0 / sqrtf (xl2*xl2 + yl2*yl2 + zl2*zl2); + xl2 *= len; + yl2 *= len; + zl2 *= len; + + xHilite = xl2 + xLook; + yHilite = yl2 + yLook; + zHilite = zl2 + zLook; + len = sqrtf (xHilite*xHilite + yHilite*yHilite + zHilite*zHilite); + if (len>THRESH2) + { + len = 1.0 / len; + xHilite *= len; + yHilite *= len; + zHilite *= len; + + h->h.x2 = twidth*4 + + (xHilite*xRight + yHilite*yRight + zHilite*zRight)*twidth*2; + + h->h.y2 = theight*4 + + (xHilite*xUp + yHilite*yUp + zHilite*zUp)*theight*2; + } + else + { + h->h.x2 = twidth*2; + h->h.y2 = theight*2; + } + + /* reflectance vectors = Up and Right */ + + l->l[0].l.dir[0] = FTOFRAC8(xRight); + l->l[0].l.dir[1] = FTOFRAC8(yRight); + l->l[0].l.dir[2] = FTOFRAC8(zRight); + l->l[1].l.dir[0] = FTOFRAC8(xUp); + l->l[1].l.dir[1] = FTOFRAC8(yUp); + l->l[1].l.dir[2] = FTOFRAC8(zUp); + l->l[0].l.col[0] = 0x00; + l->l[0].l.col[1] = 0x00; + l->l[0].l.col[2] = 0x00; + l->l[0].l.pad1 = 0x00; + l->l[0].l.colc[0] = 0x00; + l->l[0].l.colc[1] = 0x00; + l->l[0].l.colc[2] = 0x00; + l->l[0].l.pad2 = 0x00; + l->l[1].l.col[0] = 0x00; + l->l[1].l.col[1] = 0x80; + l->l[1].l.col[2] = 0x00; + l->l[1].l.pad1 = 0x00; + l->l[1].l.colc[0] = 0x00; + l->l[1].l.colc[1] = 0x80; + l->l[1].l.colc[2] = 0x00; + l->l[1].l.pad2 = 0x00; + + mf[0][0] = xRight; + mf[1][0] = yRight; + mf[2][0] = zRight; + mf[3][0] = -(xEye * xRight + yEye * yRight + zEye * zRight); + + mf[0][1] = xUp; + mf[1][1] = yUp; + mf[2][1] = zUp; + mf[3][1] = -(xEye * xUp + yEye * yUp + zEye * zUp); + + mf[0][2] = xLook; + mf[1][2] = yLook; + mf[2][2] = zLook; + mf[3][2] = -(xEye * xLook + yEye * yLook + zEye * zLook); + + mf[0][3] = 0; + mf[1][3] = 0; + mf[2][3] = 0; + mf[3][3] = 1; +} + +void guLookAtHilite (Mtx *m, LookAt *l, Hilite *h, + float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp, + float xl1, float yl1, float zl1, /* light 1 direction */ + float xl2, float yl2, float zl2, /* light 2 direction */ + int twidth, int theight) /* highlight txtr size*/ +{ + Matrix mf; + + guLookAtHiliteF(mf, l, h, xEye, yEye, zEye, xAt, yAt, zAt, + xUp, yUp, zUp, xl1, yl1, zl1, xl2, yl2, zl2, + twidth, theight); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/lookatref.c b/lib/ultralib/src/gu/lookatref.c new file mode 100644 index 0000000..3cd3b65 --- /dev/null +++ b/lib/ultralib/src/gu/lookatref.c @@ -0,0 +1,111 @@ +/************************************************************************** + * * + * 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" + + +void guLookAtReflectF(float mf[4][4], LookAt *l, + float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp) +{ + float len, xLook, yLook, zLook, xRight, yRight, zRight; + + guMtxIdentF(mf); + + xLook = xAt - xEye; + yLook = yAt - yEye; + zLook = zAt - zEye; + + /* Negate because positive Z is behind us: */ + len = -1.0 / sqrtf (xLook*xLook + yLook*yLook + zLook*zLook); + xLook *= len; + yLook *= len; + zLook *= len; + + /* Right = Up x Look */ + + xRight = yUp * zLook - zUp * yLook; + yRight = zUp * xLook - xUp * zLook; + zRight = xUp * yLook - yUp * xLook; + len = 1.0 / sqrtf (xRight*xRight + yRight*yRight + zRight*zRight); + xRight *= len; + yRight *= len; + zRight *= len; + + /* Up = Look x Right */ + + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + len = 1.0 / sqrtf (xUp*xUp + yUp*yUp + zUp*zUp); + xUp *= len; + yUp *= len; + zUp *= len; + + /* reflectance vectors = Up and Right */ + + l->l[0].l.dir[0] = FTOFRAC8(xRight); + l->l[0].l.dir[1] = FTOFRAC8(yRight); + l->l[0].l.dir[2] = FTOFRAC8(zRight); + l->l[1].l.dir[0] = FTOFRAC8(xUp); + l->l[1].l.dir[1] = FTOFRAC8(yUp); + l->l[1].l.dir[2] = FTOFRAC8(zUp); + l->l[0].l.col[0] = 0x00; + l->l[0].l.col[1] = 0x00; + l->l[0].l.col[2] = 0x00; + l->l[0].l.pad1 = 0x00; + l->l[0].l.colc[0] = 0x00; + l->l[0].l.colc[1] = 0x00; + l->l[0].l.colc[2] = 0x00; + l->l[0].l.pad2 = 0x00; + l->l[1].l.col[0] = 0x00; + l->l[1].l.col[1] = 0x80; + l->l[1].l.col[2] = 0x00; + l->l[1].l.pad1 = 0x00; + l->l[1].l.colc[0] = 0x00; + l->l[1].l.colc[1] = 0x80; + l->l[1].l.colc[2] = 0x00; + l->l[1].l.pad2 = 0x00; + + mf[0][0] = xRight; + mf[1][0] = yRight; + mf[2][0] = zRight; + mf[3][0] = -(xEye * xRight + yEye * yRight + zEye * zRight); + + mf[0][1] = xUp; + mf[1][1] = yUp; + mf[2][1] = zUp; + mf[3][1] = -(xEye * xUp + yEye * yUp + zEye * zUp); + + mf[0][2] = xLook; + mf[1][2] = yLook; + mf[2][2] = zLook; + mf[3][2] = -(xEye * xLook + yEye * yLook + zEye * zLook); + + mf[0][3] = 0; + mf[1][3] = 0; + mf[2][3] = 0; + mf[3][3] = 1; +} + +void guLookAtReflect (Mtx *m, LookAt *l, float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp) +{ + float mf[4][4]; + + guLookAtReflectF(mf, l, xEye, yEye, zEye, xAt, yAt, zAt, + xUp, yUp, zUp); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/lookatstereo.c b/lib/ultralib/src/gu/lookatstereo.c new file mode 100644 index 0000000..b60ca08 --- /dev/null +++ b/lib/ultralib/src/gu/lookatstereo.c @@ -0,0 +1,111 @@ +/************************************************************************** + * * + * 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" + +void guLookAtStereoF(float mf[4][4], float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp, float eyedist) +{ + float len, xLook, yLook, zLook, xRight, yRight, zRight; + + guMtxIdentF(mf); + + xLook = xAt - xEye; + yLook = yAt - yEye; + zLook = zAt - zEye; + + /* Negate because positive Z is behind us: */ + len = -1.0 / sqrtf (xLook*xLook + yLook*yLook + zLook*zLook); + xLook *= len; + yLook *= len; + zLook *= len; + + /* Right = Up x Look */ + + xRight = yUp * zLook - zUp * yLook; + yRight = zUp * xLook - xUp * zLook; + zRight = xUp * yLook - yUp * xLook; + len = 1.0 / sqrtf (xRight*xRight + yRight*yRight + zRight*zRight); + xRight *= len; + yRight *= len; + zRight *= len; + + /* Move eye for stereo */ + xEye += eyedist*xRight; + yEye += eyedist*yRight; + zEye += eyedist*zRight; + + /* recalculate using new eye */ + xLook = xAt - xEye; + yLook = yAt - yEye; + zLook = zAt - zEye; + + /* Negate because positive Z is behind us: */ + len = -1.0 / sqrtf (xLook*xLook + yLook*yLook + zLook*zLook); + xLook *= len; + yLook *= len; + zLook *= len; + + /* Right = Up x Look */ + + xRight = yUp * zLook - zUp * yLook; + yRight = zUp * xLook - xUp * zLook; + zRight = xUp * yLook - yUp * xLook; + len = 1.0 / sqrtf (xRight*xRight + yRight*yRight + zRight*zRight); + xRight *= len; + yRight *= len; + zRight *= len; + + + /* Up = Look x Right */ + + xUp = yLook * zRight - zLook * yRight; + yUp = zLook * xRight - xLook * zRight; + zUp = xLook * yRight - yLook * xRight; + len = 1.0 / sqrtf (xUp*xUp + yUp*yUp + zUp*zUp); + xUp *= len; + yUp *= len; + zUp *= len; + + mf[0][0] = xRight; + mf[1][0] = yRight; + mf[2][0] = zRight; + mf[3][0] = -(xEye * xRight + yEye * yRight + zEye * zRight); + + mf[0][1] = xUp; + mf[1][1] = yUp; + mf[2][1] = zUp; + mf[3][1] = -(xEye * xUp + yEye * yUp + zEye * zUp); + + mf[0][2] = xLook; + mf[1][2] = yLook; + mf[2][2] = zLook; + mf[3][2] = -(xEye * xLook + yEye * yLook + zEye * zLook); + + mf[0][3] = 0; + mf[1][3] = 0; + mf[2][3] = 0; + mf[3][3] = 1; +} + +void guLookAtStereo (Mtx *m, float xEye, float yEye, float zEye, + float xAt, float yAt, float zAt, + float xUp, float yUp, float zUp, float eyedist) +{ + Matrix mf; + + guLookAtStereoF(mf, xEye, yEye, zEye, xAt, yAt, zAt, + xUp, yUp, zUp, eyedist); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/mtxcatl.c b/lib/ultralib/src/gu/mtxcatl.c new file mode 100644 index 0000000..11f43a1 --- /dev/null +++ b/lib/ultralib/src/gu/mtxcatl.c @@ -0,0 +1,45 @@ + +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + * + */ + +/* + * File: mtxcatl.c + * Creator: hsa@sgi.com + * Create Date: Thu Nov 2 13:03:02 PST 1995 + * + */ + +#include "guint.h" + +void guMtxCatL(Mtx *m, Mtx *n, Mtx *res) +{ + float mf[4][4], nf[4][4], resf[4][4]; + + guMtxL2F(mf, m); + guMtxL2F(nf, n); + + guMtxCatF(mf, nf, resf); + + guMtxF2L(resf, res); +} diff --git a/lib/ultralib/src/gu/mtxutil.c b/lib/ultralib/src/gu/mtxutil.c new file mode 100644 index 0000000..2510558 --- /dev/null +++ b/lib/ultralib/src/gu/mtxutil.c @@ -0,0 +1,73 @@ +/************************************************************************** + * * + * 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" + +void guMtxF2L(float mf[4][4], Mtx *m) +{ + int i, j; + int e1,e2; + int *ai,*af; + + + ai=(int *) &m->m[0][0]; + af=(int *) &m->m[2][0]; + + for (i=0; i<4; i++) + for (j=0; j<2; j++) { + e1=FTOFIX32(mf[i][j*2]); + e2=FTOFIX32(mf[i][j*2+1]); + *(ai++) = ( e1 & 0xffff0000 ) | ((e2 >> 16)&0xffff); + *(af++) = ((e1 << 16) & 0xffff0000) | (e2 & 0xffff); + } +} + +void guMtxL2F(float mf[4][4], Mtx *m) +{ + int i, j; + unsigned int e1,e2; + unsigned int *ai,*af; + int q1,q2; + + ai=(unsigned int *) &m->m[0][0]; + af=(unsigned int *) &m->m[2][0]; + + for (i=0; i<4; i++) + for (j=0; j<2; j++) { + e1 = (*ai & 0xffff0000) | ((*af >> 16) & 0xffff); + e2 = ((*(ai++) << 16) & 0xffff0000) | (*(af++) & 0xffff); + q1 = *((int *)&e1); + q2 = *((int *)&e2); + + mf[i][j*2] = FIX32TOF(q1); + mf[i][j*2+1] = FIX32TOF(q2); + } +} + +void guMtxIdentF(float mf[4][4]) +{ + int i, j; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + if (i == j) mf[i][j] = 1.0; + else mf[i][j] = 0.0; +} + +void guMtxIdent(Mtx *m) +{ + float mf[4][4]; + + guMtxIdentF(mf); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/ortho.c b/lib/ultralib/src/gu/ortho.c new file mode 100644 index 0000000..9e52cb3 --- /dev/null +++ b/lib/ultralib/src/gu/ortho.c @@ -0,0 +1,41 @@ +/************************************************************************** + * * + * 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" + +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) +{ + Matrix mf; + + guOrthoF(mf, l, r, b, t, n, f, scale); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/parse_gbi.c b/lib/ultralib/src/gu/parse_gbi.c new file mode 100644 index 0000000..21cf9c3 --- /dev/null +++ b/lib/ultralib/src/gu/parse_gbi.c @@ -0,0 +1,131 @@ + +/************************************************************************** + * * + * 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 <ultra64.h> +#include <ultrahost.h> +#include <gu.h> + +#ifndef _FINALROM + +/* + * guParseGbiDL works in conjunction with the dlprint tool. dlprint must be + * running on the host Indy. guParseGbiDL, sends a bunch of blocks of data, + * with a minimum of one display list, but typically, the principle display + * list with a bunch of branched or nested display lists, as well as all the + * vertex and matrix data that will be used. After all the blocks of data + * are sent, a GU_PARSE_READY command is sent, and dlprint parses out the + * data printing it to stdout. + * + * In order to know what data to send, guParseGbiDL must step through the + * display list, find all the gSPDisplayList and gSPBranchList calls, go + * to those lists, and also find and send info for all the matrix and vertex + * calls. + */ +void guParseGbiDL(u64 *gbi_dl, u32 nbytes, u8 flags) +{ + guDLPrintCB cntlBlk; + Gfx* dlStk[11]; + s32 dlcount = 0; + Gfx *curGfx,*dlPtr,*vaddr; + s8 op; + u32 *word0; + u32 *word1; + u32 segments[16]; + u32 param, seg; + u32 paddr,len; + + + cntlBlk.dataSize = nbytes; + cntlBlk.flags = flags; + cntlBlk.dlType = GU_PARSE_GBI_TYPE; + cntlBlk.paddr = osVirtualToPhysical(gbi_dl); + + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost(gbi_dl,nbytes); + + dlStk[0] = (Gfx*)gbi_dl; + while((dlcount >= 0) && (dlcount <= 10)) + { + curGfx = dlStk[dlcount]; /* get the current graphics display list */ + op = *((s8*)curGfx); /* get the first byte */ + dlStk[dlcount]++; /* increment to next gfx command */ + switch(op) + { + case G_MOVEWORD: + word0 = (u32*)curGfx; /* get ptr to first word */ + if(((*word0) & 0x000000ff) == G_MW_SEGMENT) + { + u32 seg; + seg = (((*word0) & 0x00ffff00) >> 8) >> 2; + word1 = word0 + 1; + segments[seg] = *word1; + } + break; + case G_ENDDL: + dlcount--; + break; + case G_DL: + word0 = (u32*)curGfx; /* get ptr to first word */ + param = ((*word0) & 0x00ff0000) >> 16; /* get param */ + word1 = word0 + 1; /* get pointer to second word */ + seg = ((*word1) & 0x0f000000) >> 24; /* get the segment */ + paddr = segments[seg] + ((*word1) & 0x00ffffff); + vaddr = (Gfx*)osPhysicalToVirtual(paddr); + len = 1; + dlPtr = vaddr; + while((*(s8*)dlPtr) != G_ENDDL) + { + len++; + dlPtr++; + } + len *= sizeof(Gfx); + + cntlBlk.dataSize = len; + cntlBlk.dlType = GU_PARSE_GBI_TYPE; + cntlBlk.paddr = paddr; + + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost((u8*)vaddr,len); + if(param == G_DL_PUSH) + { + if(dlcount < 10) + dlcount++; + else + osSyncPrintf("Display lists nested too deep!!!\n"); + } + dlStk[dlcount] = (Gfx*)vaddr; + break; + case G_VTX: + case G_MOVEMEM: + case G_MTX: + word0 = (u32*)curGfx; /* get ptr to first word */ + word1 = word0 + 1; /* get pointer to second word */ + seg = ((*word1) & 0x0f000000) >> 24; /* get the segment */ + paddr = segments[seg] + ((*word1) & 0x00ffffff); + vaddr = (Gfx*)osPhysicalToVirtual(paddr); + len = (*word0) & 0x0000ffff; + cntlBlk.dataSize = len; /* always send 32 bytes, the most used */ + cntlBlk.dlType = GU_PARSE_MEM_BLOCK; + cntlBlk.paddr = paddr; + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost((u8*)vaddr,len); + break; + + } + } + + cntlBlk.dlType = GU_PARSE_READY; + osWriteHost(&cntlBlk,sizeof(cntlBlk)); +} + +#endif + diff --git a/lib/ultralib/src/gu/parse_rdp.c b/lib/ultralib/src/gu/parse_rdp.c new file mode 100644 index 0000000..c17c978 --- /dev/null +++ b/lib/ultralib/src/gu/parse_rdp.c @@ -0,0 +1,36 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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 <ultra64.h> +#include <ultrahost.h> +#include <gu.h> + +/* guParseRdpDL works in conjunction with dlprint which must be running on + * the host Indy. guParseRdpDL simple uses the hostio routines to send the + * display list to the Indy, and dlprint does all the parsing. + */ + +#ifndef _FINALROM +void guParseRdpDL(u64 *rdp_dl, u64 nbytes, u8 flags) +{ + guDLPrintCB cntlBlk; + + cntlBlk.dataSize = nbytes; + cntlBlk.flags = flags; + cntlBlk.dlType = GU_PARSE_RDP_TYPE; + cntlBlk.paddr = osVirtualToPhysical(rdp_dl); + + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost(rdp_dl,nbytes); + +} + +#endif diff --git a/lib/ultralib/src/gu/parse_string.c b/lib/ultralib/src/gu/parse_string.c new file mode 100644 index 0000000..71a58a8 --- /dev/null +++ b/lib/ultralib/src/gu/parse_string.c @@ -0,0 +1,35 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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 <ultra64.h> +#include <ultrahost.h> +#include <gu.h> + +/* guParseString works in conjunction with dlprint which must be running on + * the host Indy. guParseString simply uses the hostio routines to send the + * string to the Indy, and dlprint does all the parsing. + */ + +#ifndef _FINALROM +void guParseString(char *StringPointer, u64 nbytes) +{ + guDLPrintCB cntlBlk; + + cntlBlk.dataSize = nbytes /* /8 + ((nbytes%8) != 0) */; + cntlBlk.dlType = GU_PARSE_STRING_TYPE; + cntlBlk.paddr = osVirtualToPhysical((u64 *) StringPointer); + + osWriteHost(&cntlBlk,sizeof(cntlBlk)); + osWriteHost((u64 *) StringPointer,nbytes); + +} + +#endif diff --git a/lib/ultralib/src/gu/perspective.c b/lib/ultralib/src/gu/perspective.c new file mode 100644 index 0000000..be571d4 --- /dev/null +++ b/lib/ultralib/src/gu/perspective.c @@ -0,0 +1,58 @@ + +/************************************************************************** + * * + * 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" +#include <ultratypes.h> + +void guPerspectiveF(float mf[4][4], u16 *perspNorm, float fovy, float aspect, float near, float far, float scale) +{ + float cot; + int i, j; + + guMtxIdentF(mf); + + fovy *= 3.1415926 / 180.0; + cot = cosf (fovy/2) / sinf (fovy/2); + + mf[0][0] = cot / aspect; + mf[1][1] = cot; + mf[2][2] = (near + far) / (near - far); + mf[2][3] = -1; + mf[3][2] = (2 * near * far) / (near - far); + mf[3][3] = 0; + + for (i=0; i<4; i++) + for (j=0; j<4; j++) + mf[i][j] *= scale; + + if (perspNorm != (u16 *) NULL) { + if (near+far<=2.0) { + *perspNorm = (u16) 0xFFFF; + } else { + *perspNorm = (u16) ((2.0*65536.0)/(near+far)); + if (*perspNorm<=0) + *perspNorm = (u16) 0x0001; + } + } +} + +void guPerspective(Mtx *m, u16 *perspNorm, float fovy, float aspect, float near, float far, float scale) +{ + Matrix mf; + + guPerspectiveF(mf, perspNorm, fovy, aspect, near, far, scale); + + guMtxF2L(mf, m); +} + + diff --git a/lib/ultralib/src/gu/position.c b/lib/ultralib/src/gu/position.c new file mode 100644 index 0000000..52cdd96 --- /dev/null +++ b/lib/ultralib/src/gu/position.c @@ -0,0 +1,73 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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" + +/* + * Return position matrix given roll, pitch, and yaw in degrees + * plus scale and position. + * + * r = roll (degrees) + * p = pitch (degrees) + * h = yaw (degrees) + * s = scale + * x,y,z = position (world coordinates) + * + */ + +void guPositionF(float mf[4][4], float r, float p, float h, float s, + float x, float y, float z) +{ + static float dtor = 3.1415926 / 180.0; + float sinr, sinp, sinh; + float cosr, cosp, cosh; + + r *= dtor; + p *= dtor; + h *= dtor; + sinr = sinf(r); + cosr = cosf(r); + sinp = sinf(p); + cosp = cosf(p); + sinh = sinf(h); + cosh = cosf(h); + + mf[0][0] = (cosp*cosh) * s; + mf[0][1] = (cosp*sinh) * s; + mf[0][2] = (-sinp) * s; + mf[0][3] = 0.0; + + mf[1][0] = (sinr*sinp*cosh - cosr*sinh) * s; + mf[1][1] = (sinr*sinp*sinh + cosr*cosh) * s; + mf[1][2] = (sinr*cosp) * s; + mf[1][3] = 0.0; + + mf[2][0] = (cosr*sinp*cosh + sinr*sinh) * s; + mf[2][1] = (cosr*sinp*sinh - sinr*cosh) * s; + mf[2][2] = (cosr*cosp) * s; + mf[2][3] = 0.0; + + mf[3][0] = x; + mf[3][1] = y; + mf[3][2] = z; + mf[3][3] = 1.0; +} + +void guPosition(Mtx *m, float r, float p, float h, float s, + float x, float y, float z) +{ + float mf[4][4]; + + guPositionF(mf, r, p, h, s, x, y, z); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/poslight.c b/lib/ultralib/src/gu/poslight.c new file mode 100644 index 0000000..389a04d --- /dev/null +++ b/lib/ultralib/src/gu/poslight.c @@ -0,0 +1,69 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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" + + +/* + * define a positional light. + * this function must be called anytime the light or object moves. + * + * pl = (input) positional light description. + * l = (output) directiona light description for gSPLight or gSPSetLightsN. + * *Ob = position of (center of) object to be lit. + * + */ +#define THRESH1 0.01 +#define THRESH2 0.1 +void guPosLight(PositionalLight *pl, Light *l, + float xOb, float yOb, float zOb) +{ + float x,y,z,d,a; + + + x = pl->pos[0]-xOb; + y = pl->pos[1]-yOb; + z = pl->pos[2]-zOb; + d = sqrtf(x*x + y*y + z*z); + + a = d*pl->a1 + pl->a2; + if (a<THRESH1) + a=100.0; + else + a = 1/a; + + if (d<THRESH1) { + l->l.dir[0] = 0; + l->l.dir[1] = 0; + l->l.dir[2] = -120; + + l->l.col[0] = 0; + l->l.col[1] = 0; + l->l.col[2] = 0; + l->l.colc[0] = 0; + l->l.colc[1] = 0; + l->l.colc[2] = 0; + } else { + d = 1/d; + l->l.dir[0] = 120.0*x*d; + l->l.dir[1] = 120.0*y*d; + l->l.dir[2] = 120.0*z*d; + + l->l.col[0] = pl->col[0]*a; + l->l.col[1] = pl->col[1]*a; + l->l.col[2] = pl->col[2]*a; + l->l.colc[0] = pl->col[0]*a; + l->l.colc[1] = pl->col[1]*a; + l->l.colc[2] = pl->col[2]*a; + } + +} diff --git a/lib/ultralib/src/gu/poslighthil.c b/lib/ultralib/src/gu/poslighthil.c new file mode 100644 index 0000000..259fe8c --- /dev/null +++ b/lib/ultralib/src/gu/poslighthil.c @@ -0,0 +1,168 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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" + + +/* + * define 2 positional lights with highlights. + * this function must be called anytime the viewpoint, light or object moves. + * + * pl1 = (input) positional light#1 description. + * pl2 = (input) positional light#2 description. + * l1 = (output) directional light desc. #1 for gSPLight or gSPSetLightsN. + * l2 = (output) directional light desc. #2 for gSPLight or gSPSetLightsN. + * *Eye = position of eye (viewpoint). (usually same as in LookAt command.) + * *Ob = position of (center of) object to be lit. + * *Ob = up vector (usually same as in LookAt command). + * twidth = width of texture map used for highlight. + * theight = height of texture map used for highlight. + * + */ +#define THRESH2 0.01 +#define THRESH3 0.1 +void guPosLightHilite(PositionalLight *pl1, PositionalLight *pl2, + Light *l1, Light *l2, + LookAt *l, Hilite *h, + float xEye, float yEye, float zEye, + float xOb, float yOb, float zOb, + float xUp, float yUp, float zUp, + int twidth, int theight) /* hilite txtr size*/ +{ + float x,y,z,d,a; + Mtx m; + + +/* + * light 1, diffuse + */ + x = pl1->pos[0]-xOb; + y = pl1->pos[1]-yOb; + z = pl1->pos[2]-zOb; + d = sqrtf(x*x + y*y + z*z); + + a=d*pl1->a1 + pl1->a2; + if (a<THRESH2) + a=100.0; + else + a = 1/a; + + if (d<THRESH2) { + l1->l.dir[0] = 0; + l1->l.dir[1] = 0; + l1->l.dir[2] = -120; + + l1->l.col[0] = 0; + l1->l.col[1] = 0; + l1->l.col[2] = 0; + l1->l.colc[0] = 0; + l1->l.colc[1] = 0; + l1->l.colc[2] = 0; + } else { + d = 1/d; + l1->l.dir[0] = 120.0*x*d; + l1->l.dir[1] = 120.0*y*d; + l1->l.dir[2] = 120.0*z*d; + + l1->l.col[0] = pl1->col[0]*a; + l1->l.col[1] = pl1->col[1]*a; + l1->l.col[2] = pl1->col[2]*a; + l1->l.colc[0] = pl1->col[0]*a; + l1->l.colc[1] = pl1->col[1]*a; + l1->l.colc[2] = pl1->col[2]*a; + } + + +/* + * light 2, diffuse + */ + x = pl2->pos[0]-xOb; + y = pl2->pos[1]-yOb; + z = pl2->pos[2]-zOb; + d = sqrtf(x*x + y*y + z*z); + + a = d*pl2->a1 + pl2->a2; + if (a<THRESH2) + a=100.0; + else + a = 1/a; + + if (d<THRESH2) { + l2->l.dir[0] = 0; + l2->l.dir[1] = 0; + l2->l.dir[2] = -120; + + l2->l.col[0] = 0; + l2->l.col[1] = 0; + l2->l.col[2] = 0; + l2->l.colc[0] = 0; + l2->l.colc[1] = 0; + l2->l.colc[2] = 0; + } else { + d = 1/d; + l2->l.dir[0] = 120.0*x*d; + l2->l.dir[1] = 120.0*y*d; + l2->l.dir[2] = 120.0*z*d; + + l2->l.col[0] = pl2->col[0]*a; + l2->l.col[1] = pl2->col[1]*a; + l2->l.col[2] = pl2->col[2]*a; + l2->l.colc[0] = pl2->col[0]*a; + l2->l.colc[1] = pl2->col[1]*a; + l2->l.colc[2] = pl2->col[2]*a; + } + + +/* + * Hilight factors + */ + x = xOb-xEye; + y = yOb-yEye; + z = zOb-zEye; + if (sqrtf(x*x + y*y + z*z)<THRESH3) { + h->h.x1 = twidth*2; + h->h.y1 = twidth*2; + h->h.x2 = twidth*2; + h->h.y2 = twidth*2; + l->l[0].l.dir[0] = 0; + l->l[0].l.dir[1] = 0; + l->l[0].l.dir[2] = 0; + l->l[1].l.dir[0] = 0; + l->l[1].l.dir[1] = 0; + l->l[1].l.dir[2] = 0; + l->l[0].l.col[0] = 0x00; + l->l[0].l.col[1] = 0x00; + l->l[0].l.col[2] = 0x00; + l->l[0].l.pad1 = 0x00; + l->l[0].l.colc[0] = 0x00; + l->l[0].l.colc[1] = 0x00; + l->l[0].l.colc[2] = 0x00; + l->l[0].l.pad2 = 0x00; + l->l[1].l.col[0] = 0x00; + l->l[1].l.col[1] = 0x80; + l->l[1].l.col[2] = 0x00; + l->l[1].l.pad1 = 0x00; + l->l[1].l.colc[0] = 0x00; + l->l[1].l.colc[1] = 0x80; + l->l[1].l.colc[2] = 0x00; + l->l[1].l.pad2 = 0x00; + } else { + guLookAtHilite(&m, l, h, + xEye, yEye, zEye, + xOb, yOb, zOb, + xUp, yUp, zUp, + l1->l.dir[0], l1->l.dir[1], l1->l.dir[2], + l2->l.dir[0], l2->l.dir[1], l2->l.dir[2], + twidth, theight); + } +} + diff --git a/lib/ultralib/src/gu/random.c b/lib/ultralib/src/gu/random.c new file mode 100644 index 0000000..32cfde3 --- /dev/null +++ b/lib/ultralib/src/gu/random.c @@ -0,0 +1,33 @@ +/************************************************************************** + * * + * Copyright (C) 1995, 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" + +/* + * Return a pseudorandom 32 bit number + * try the RAND macro too + * + */ +int guRandom(void) +{ + static unsigned int xseed = 174823885; + unsigned int x; + + x = (xseed<<2) + 2; + + x *= (x+1); + x = x >> 2; + + xseed = x; + + return( x ); +} diff --git a/lib/ultralib/src/gu/readme.txt b/lib/ultralib/src/gu/readme.txt new file mode 100644 index 0000000..114174e --- /dev/null +++ b/lib/ultralib/src/gu/readme.txt @@ -0,0 +1,17 @@ +Among the gu Functions, the following were replaced with the newly +created high speed versions. With the current version OS they are +not being used. + +guMtxIdent +guMtxIdentF +guScale +guScaleF +guNormalize +guTranslate +guTranslateF +guMtxF2L +guRotateF +guMtxL2F +guMtxCatF + +The newly created functions are installed in the mgu directory. diff --git a/lib/ultralib/src/gu/rotate.c b/lib/ultralib/src/gu/rotate.c new file mode 100644 index 0000000..eceb096 --- /dev/null +++ b/lib/ultralib/src/gu/rotate.c @@ -0,0 +1,63 @@ +/************************************************************************** + * * + * 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" + +void guRotateF(float mf[4][4], float a, float x, float y, float z) +{ + static float dtor = 3.1415926 / 180.0; + float sine; + float cosine; + float ab, bc, ca, t; + float xxsine; + float yxsine; + float zxsine; + + guNormalize(&x, &y, &z); + a *= dtor; + sine = sinf(a); + cosine = cosf(a); + t = (1-cosine); + ab = x*y*t; + bc = y*z*t; + ca = z*x*t; + + guMtxIdentF(mf); + + xxsine = x * sine; + yxsine = y * sine; + zxsine = z * sine; + + t = x*x; + mf[0][0] = t+cosine*(1-t); + mf[2][1] = bc-xxsine; + mf[1][2] = bc+xxsine; + + t = y*y; + mf[1][1] = t+cosine*(1-t); + mf[2][0] = ca+yxsine; + mf[0][2] = ca-yxsine; + + t = z*z; + mf[2][2] = t+cosine*(1-t); + mf[1][0] = ab-zxsine; + mf[0][1] = ab+zxsine; +} + +void guRotate(Mtx *m, float a, float x, float y, float z) +{ + Matrix mf; + + guRotateF(mf, a, x, y, z); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/rotaterpy.c b/lib/ultralib/src/gu/rotaterpy.c new file mode 100644 index 0000000..c239d21 --- /dev/null +++ b/lib/ultralib/src/gu/rotaterpy.c @@ -0,0 +1,58 @@ +/************************************************************************** + * * + * 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" + +/* + * Return rotation matrix given roll, pitch, and yaw in degrees + * + */ + +void guRotateRPYF(float mf[4][4], float r, float p, float h) +{ + static float dtor = 3.1415926 / 180.0; + float sinr, sinp, sinh; + float cosr, cosp, cosh; + + r *= dtor; + p *= dtor; + h *= dtor; + sinr = sinf(r); + cosr = cosf(r); + sinp = sinf(p); + cosp = cosf(p); + sinh = sinf(h); + cosh = cosf(h); + + guMtxIdentF(mf); + + mf[0][0] = cosp*cosh; + mf[0][1] = cosp*sinh; + mf[0][2] = -sinp; + + mf[1][0] = sinr*sinp*cosh - cosr*sinh; + mf[1][1] = sinr*sinp*sinh + cosr*cosh; + mf[1][2] = sinr*cosp; + + mf[2][0] = cosr*sinp*cosh + sinr*sinh; + mf[2][1] = cosr*sinp*sinh - sinr*cosh; + mf[2][2] = cosr*cosp; +} + +void guRotateRPY(Mtx *m, float r, float p, float h) +{ + Matrix mf; + + guRotateRPYF(mf, r, p, h); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/gu/sinf.c b/lib/ultralib/src/gu/sinf.c new file mode 100644 index 0000000..f4bb1ad --- /dev/null +++ b/lib/ultralib/src/gu/sinf.c @@ -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.3 $ + * $Date: 1998/10/09 06:14:51 $ + * $Author: has $ + * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/libultra/monegi/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 +fsin( 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 ); +} + diff --git a/lib/ultralib/src/gu/sins.c b/lib/ultralib/src/gu/sins.c new file mode 100644 index 0000000..b24851f --- /dev/null +++ b/lib/ultralib/src/gu/sins.c @@ -0,0 +1,61 @@ +/************************************************************************** + * * + * 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: sins.c + * $Revision: 1.3 $ + * $Date: 1998/10/09 06:15:00 $ + * $Author: has $ + * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/libultra/monegi/gu/sins.c,v $ + * + * ==================================================================== + * ==================================================================== + */ + +/* coefficients for polynomial approximation of sin on +/- pi/2 */ + +/* ==================================================================== + * + * FunctionName sins + * + * Description computes sine of arg + * + * ==================================================================== + */ + +#include "sintable.h" + +signed short +sins( unsigned short x ) +{ + /* 0 <= x < 0x10000 ==> 0 <= x < 2PI */ + + signed short val; + + x >>= 4; /* Now range 0 <= x < 0x1000 */ + + if (x & 0x400) { + val = sintable[0x3ff - (x & 0x3ff)]; + } else { + val = sintable[x & 0x3ff]; + } + + if (x & 0x800) { + return -val; + } else { + return val; + } +} diff --git a/lib/ultralib/src/gu/sintable.h b/lib/ultralib/src/gu/sintable.h new file mode 100644 index 0000000..b5e1a45 --- /dev/null +++ b/lib/ultralib/src/gu/sintable.h @@ -0,0 +1,1031 @@ + +/* + * Do not edit this file -- it was generated by "maketable". + */ + +static signed short sintable[0x400] = { + 0x0000, + 0x0032, + 0x0064, + 0x0096, + 0x00c9, + 0x00fb, + 0x012d, + 0x0160, + 0x0192, + 0x01c4, + 0x01f7, + 0x0229, + 0x025b, + 0x028e, + 0x02c0, + 0x02f2, + 0x0324, + 0x0357, + 0x0389, + 0x03bb, + 0x03ee, + 0x0420, + 0x0452, + 0x0484, + 0x04b7, + 0x04e9, + 0x051b, + 0x054e, + 0x0580, + 0x05b2, + 0x05e4, + 0x0617, + 0x0649, + 0x067b, + 0x06ad, + 0x06e0, + 0x0712, + 0x0744, + 0x0776, + 0x07a9, + 0x07db, + 0x080d, + 0x083f, + 0x0871, + 0x08a4, + 0x08d6, + 0x0908, + 0x093a, + 0x096c, + 0x099f, + 0x09d1, + 0x0a03, + 0x0a35, + 0x0a67, + 0x0a99, + 0x0acb, + 0x0afe, + 0x0b30, + 0x0b62, + 0x0b94, + 0x0bc6, + 0x0bf8, + 0x0c2a, + 0x0c5c, + 0x0c8e, + 0x0cc0, + 0x0cf2, + 0x0d25, + 0x0d57, + 0x0d89, + 0x0dbb, + 0x0ded, + 0x0e1f, + 0x0e51, + 0x0e83, + 0x0eb5, + 0x0ee7, + 0x0f19, + 0x0f4b, + 0x0f7c, + 0x0fae, + 0x0fe0, + 0x1012, + 0x1044, + 0x1076, + 0x10a8, + 0x10da, + 0x110c, + 0x113e, + 0x116f, + 0x11a1, + 0x11d3, + 0x1205, + 0x1237, + 0x1269, + 0x129a, + 0x12cc, + 0x12fe, + 0x1330, + 0x1361, + 0x1393, + 0x13c5, + 0x13f6, + 0x1428, + 0x145a, + 0x148c, + 0x14bd, + 0x14ef, + 0x1520, + 0x1552, + 0x1584, + 0x15b5, + 0x15e7, + 0x1618, + 0x164a, + 0x167b, + 0x16ad, + 0x16df, + 0x1710, + 0x1741, + 0x1773, + 0x17a4, + 0x17d6, + 0x1807, + 0x1839, + 0x186a, + 0x189b, + 0x18cd, + 0x18fe, + 0x1930, + 0x1961, + 0x1992, + 0x19c3, + 0x19f5, + 0x1a26, + 0x1a57, + 0x1a88, + 0x1aba, + 0x1aeb, + 0x1b1c, + 0x1b4d, + 0x1b7e, + 0x1baf, + 0x1be1, + 0x1c12, + 0x1c43, + 0x1c74, + 0x1ca5, + 0x1cd6, + 0x1d07, + 0x1d38, + 0x1d69, + 0x1d9a, + 0x1dcb, + 0x1dfc, + 0x1e2d, + 0x1e5d, + 0x1e8e, + 0x1ebf, + 0x1ef0, + 0x1f21, + 0x1f52, + 0x1f82, + 0x1fb3, + 0x1fe4, + 0x2015, + 0x2045, + 0x2076, + 0x20a7, + 0x20d7, + 0x2108, + 0x2139, + 0x2169, + 0x219a, + 0x21ca, + 0x21fb, + 0x222b, + 0x225c, + 0x228c, + 0x22bd, + 0x22ed, + 0x231d, + 0x234e, + 0x237e, + 0x23ae, + 0x23df, + 0x240f, + 0x243f, + 0x2470, + 0x24a0, + 0x24d0, + 0x2500, + 0x2530, + 0x2560, + 0x2591, + 0x25c1, + 0x25f1, + 0x2621, + 0x2651, + 0x2681, + 0x26b1, + 0x26e1, + 0x2711, + 0x2740, + 0x2770, + 0x27a0, + 0x27d0, + 0x2800, + 0x2830, + 0x285f, + 0x288f, + 0x28bf, + 0x28ee, + 0x291e, + 0x294e, + 0x297d, + 0x29ad, + 0x29dd, + 0x2a0c, + 0x2a3c, + 0x2a6b, + 0x2a9b, + 0x2aca, + 0x2af9, + 0x2b29, + 0x2b58, + 0x2b87, + 0x2bb7, + 0x2be6, + 0x2c15, + 0x2c44, + 0x2c74, + 0x2ca3, + 0x2cd2, + 0x2d01, + 0x2d30, + 0x2d5f, + 0x2d8e, + 0x2dbd, + 0x2dec, + 0x2e1b, + 0x2e4a, + 0x2e79, + 0x2ea8, + 0x2ed7, + 0x2f06, + 0x2f34, + 0x2f63, + 0x2f92, + 0x2fc0, + 0x2fef, + 0x301e, + 0x304c, + 0x307b, + 0x30a9, + 0x30d8, + 0x3107, + 0x3135, + 0x3163, + 0x3192, + 0x31c0, + 0x31ef, + 0x321d, + 0x324b, + 0x3279, + 0x32a8, + 0x32d6, + 0x3304, + 0x3332, + 0x3360, + 0x338e, + 0x33bc, + 0x33ea, + 0x3418, + 0x3446, + 0x3474, + 0x34a2, + 0x34d0, + 0x34fe, + 0x352b, + 0x3559, + 0x3587, + 0x35b5, + 0x35e2, + 0x3610, + 0x363d, + 0x366b, + 0x3698, + 0x36c6, + 0x36f3, + 0x3721, + 0x374e, + 0x377c, + 0x37a9, + 0x37d6, + 0x3803, + 0x3831, + 0x385e, + 0x388b, + 0x38b8, + 0x38e5, + 0x3912, + 0x393f, + 0x396c, + 0x3999, + 0x39c6, + 0x39f3, + 0x3a20, + 0x3a4d, + 0x3a79, + 0x3aa6, + 0x3ad3, + 0x3b00, + 0x3b2c, + 0x3b59, + 0x3b85, + 0x3bb2, + 0x3bde, + 0x3c0b, + 0x3c37, + 0x3c64, + 0x3c90, + 0x3cbc, + 0x3ce9, + 0x3d15, + 0x3d41, + 0x3d6d, + 0x3d99, + 0x3dc5, + 0x3df1, + 0x3e1d, + 0x3e49, + 0x3e75, + 0x3ea1, + 0x3ecd, + 0x3ef9, + 0x3f25, + 0x3f50, + 0x3f7c, + 0x3fa8, + 0x3fd3, + 0x3fff, + 0x402b, + 0x4056, + 0x4082, + 0x40ad, + 0x40d8, + 0x4104, + 0x412f, + 0x415a, + 0x4186, + 0x41b1, + 0x41dc, + 0x4207, + 0x4232, + 0x425d, + 0x4288, + 0x42b3, + 0x42de, + 0x4309, + 0x4334, + 0x435f, + 0x4389, + 0x43b4, + 0x43df, + 0x4409, + 0x4434, + 0x445f, + 0x4489, + 0x44b4, + 0x44de, + 0x4508, + 0x4533, + 0x455d, + 0x4587, + 0x45b1, + 0x45dc, + 0x4606, + 0x4630, + 0x465a, + 0x4684, + 0x46ae, + 0x46d8, + 0x4702, + 0x472c, + 0x4755, + 0x477f, + 0x47a9, + 0x47d2, + 0x47fc, + 0x4826, + 0x484f, + 0x4879, + 0x48a2, + 0x48cc, + 0x48f5, + 0x491e, + 0x4948, + 0x4971, + 0x499a, + 0x49c3, + 0x49ec, + 0x4a15, + 0x4a3e, + 0x4a67, + 0x4a90, + 0x4ab9, + 0x4ae2, + 0x4b0b, + 0x4b33, + 0x4b5c, + 0x4b85, + 0x4bad, + 0x4bd6, + 0x4bfe, + 0x4c27, + 0x4c4f, + 0x4c78, + 0x4ca0, + 0x4cc8, + 0x4cf0, + 0x4d19, + 0x4d41, + 0x4d69, + 0x4d91, + 0x4db9, + 0x4de1, + 0x4e09, + 0x4e31, + 0x4e58, + 0x4e80, + 0x4ea8, + 0x4ed0, + 0x4ef7, + 0x4f1f, + 0x4f46, + 0x4f6e, + 0x4f95, + 0x4fbd, + 0x4fe4, + 0x500b, + 0x5032, + 0x505a, + 0x5081, + 0x50a8, + 0x50cf, + 0x50f6, + 0x511d, + 0x5144, + 0x516b, + 0x5191, + 0x51b8, + 0x51df, + 0x5205, + 0x522c, + 0x5253, + 0x5279, + 0x52a0, + 0x52c6, + 0x52ec, + 0x5313, + 0x5339, + 0x535f, + 0x5385, + 0x53ab, + 0x53d1, + 0x53f7, + 0x541d, + 0x5443, + 0x5469, + 0x548f, + 0x54b5, + 0x54da, + 0x5500, + 0x5525, + 0x554b, + 0x5571, + 0x5596, + 0x55bb, + 0x55e1, + 0x5606, + 0x562b, + 0x5650, + 0x5675, + 0x569b, + 0x56c0, + 0x56e5, + 0x5709, + 0x572e, + 0x5753, + 0x5778, + 0x579d, + 0x57c1, + 0x57e6, + 0x580a, + 0x582f, + 0x5853, + 0x5878, + 0x589c, + 0x58c0, + 0x58e5, + 0x5909, + 0x592d, + 0x5951, + 0x5975, + 0x5999, + 0x59bd, + 0x59e1, + 0x5a04, + 0x5a28, + 0x5a4c, + 0x5a6f, + 0x5a93, + 0x5ab7, + 0x5ada, + 0x5afd, + 0x5b21, + 0x5b44, + 0x5b67, + 0x5b8b, + 0x5bae, + 0x5bd1, + 0x5bf4, + 0x5c17, + 0x5c3a, + 0x5c5d, + 0x5c7f, + 0x5ca2, + 0x5cc5, + 0x5ce7, + 0x5d0a, + 0x5d2d, + 0x5d4f, + 0x5d71, + 0x5d94, + 0x5db6, + 0x5dd8, + 0x5dfa, + 0x5e1d, + 0x5e3f, + 0x5e61, + 0x5e83, + 0x5ea5, + 0x5ec6, + 0x5ee8, + 0x5f0a, + 0x5f2c, + 0x5f4d, + 0x5f6f, + 0x5f90, + 0x5fb2, + 0x5fd3, + 0x5ff4, + 0x6016, + 0x6037, + 0x6058, + 0x6079, + 0x609a, + 0x60bb, + 0x60dc, + 0x60fd, + 0x611e, + 0x613e, + 0x615f, + 0x6180, + 0x61a0, + 0x61c1, + 0x61e1, + 0x6202, + 0x6222, + 0x6242, + 0x6263, + 0x6283, + 0x62a3, + 0x62c3, + 0x62e3, + 0x6303, + 0x6323, + 0x6342, + 0x6362, + 0x6382, + 0x63a1, + 0x63c1, + 0x63e0, + 0x6400, + 0x641f, + 0x643f, + 0x645e, + 0x647d, + 0x649c, + 0x64bb, + 0x64da, + 0x64f9, + 0x6518, + 0x6537, + 0x6556, + 0x6574, + 0x6593, + 0x65b2, + 0x65d0, + 0x65ef, + 0x660d, + 0x662b, + 0x664a, + 0x6668, + 0x6686, + 0x66a4, + 0x66c2, + 0x66e0, + 0x66fe, + 0x671c, + 0x673a, + 0x6757, + 0x6775, + 0x6792, + 0x67b0, + 0x67cd, + 0x67eb, + 0x6808, + 0x6825, + 0x6843, + 0x6860, + 0x687d, + 0x689a, + 0x68b7, + 0x68d4, + 0x68f1, + 0x690d, + 0x692a, + 0x6947, + 0x6963, + 0x6980, + 0x699c, + 0x69b9, + 0x69d5, + 0x69f1, + 0x6a0e, + 0x6a2a, + 0x6a46, + 0x6a62, + 0x6a7e, + 0x6a9a, + 0x6ab5, + 0x6ad1, + 0x6aed, + 0x6b08, + 0x6b24, + 0x6b40, + 0x6b5b, + 0x6b76, + 0x6b92, + 0x6bad, + 0x6bc8, + 0x6be3, + 0x6bfe, + 0x6c19, + 0x6c34, + 0x6c4f, + 0x6c6a, + 0x6c84, + 0x6c9f, + 0x6cba, + 0x6cd4, + 0x6cef, + 0x6d09, + 0x6d23, + 0x6d3e, + 0x6d58, + 0x6d72, + 0x6d8c, + 0x6da6, + 0x6dc0, + 0x6dda, + 0x6df3, + 0x6e0d, + 0x6e27, + 0x6e40, + 0x6e5a, + 0x6e73, + 0x6e8d, + 0x6ea6, + 0x6ebf, + 0x6ed9, + 0x6ef2, + 0x6f0b, + 0x6f24, + 0x6f3d, + 0x6f55, + 0x6f6e, + 0x6f87, + 0x6fa0, + 0x6fb8, + 0x6fd1, + 0x6fe9, + 0x7002, + 0x701a, + 0x7032, + 0x704a, + 0x7062, + 0x707a, + 0x7092, + 0x70aa, + 0x70c2, + 0x70da, + 0x70f2, + 0x7109, + 0x7121, + 0x7138, + 0x7150, + 0x7167, + 0x717e, + 0x7196, + 0x71ad, + 0x71c4, + 0x71db, + 0x71f2, + 0x7209, + 0x7220, + 0x7236, + 0x724d, + 0x7264, + 0x727a, + 0x7291, + 0x72a7, + 0x72bd, + 0x72d4, + 0x72ea, + 0x7300, + 0x7316, + 0x732c, + 0x7342, + 0x7358, + 0x736e, + 0x7383, + 0x7399, + 0x73ae, + 0x73c4, + 0x73d9, + 0x73ef, + 0x7404, + 0x7419, + 0x742e, + 0x7443, + 0x7458, + 0x746d, + 0x7482, + 0x7497, + 0x74ac, + 0x74c0, + 0x74d5, + 0x74ea, + 0x74fe, + 0x7512, + 0x7527, + 0x753b, + 0x754f, + 0x7563, + 0x7577, + 0x758b, + 0x759f, + 0x75b3, + 0x75c7, + 0x75da, + 0x75ee, + 0x7601, + 0x7615, + 0x7628, + 0x763b, + 0x764f, + 0x7662, + 0x7675, + 0x7688, + 0x769b, + 0x76ae, + 0x76c1, + 0x76d3, + 0x76e6, + 0x76f9, + 0x770b, + 0x771e, + 0x7730, + 0x7742, + 0x7754, + 0x7767, + 0x7779, + 0x778b, + 0x779d, + 0x77af, + 0x77c0, + 0x77d2, + 0x77e4, + 0x77f5, + 0x7807, + 0x7818, + 0x782a, + 0x783b, + 0x784c, + 0x785d, + 0x786e, + 0x787f, + 0x7890, + 0x78a1, + 0x78b2, + 0x78c3, + 0x78d3, + 0x78e4, + 0x78f4, + 0x7905, + 0x7915, + 0x7925, + 0x7936, + 0x7946, + 0x7956, + 0x7966, + 0x7976, + 0x7985, + 0x7995, + 0x79a5, + 0x79b5, + 0x79c4, + 0x79d4, + 0x79e3, + 0x79f2, + 0x7a02, + 0x7a11, + 0x7a20, + 0x7a2f, + 0x7a3e, + 0x7a4d, + 0x7a5b, + 0x7a6a, + 0x7a79, + 0x7a87, + 0x7a96, + 0x7aa4, + 0x7ab3, + 0x7ac1, + 0x7acf, + 0x7add, + 0x7aeb, + 0x7af9, + 0x7b07, + 0x7b15, + 0x7b23, + 0x7b31, + 0x7b3e, + 0x7b4c, + 0x7b59, + 0x7b67, + 0x7b74, + 0x7b81, + 0x7b8e, + 0x7b9b, + 0x7ba8, + 0x7bb5, + 0x7bc2, + 0x7bcf, + 0x7bdc, + 0x7be8, + 0x7bf5, + 0x7c02, + 0x7c0e, + 0x7c1a, + 0x7c27, + 0x7c33, + 0x7c3f, + 0x7c4b, + 0x7c57, + 0x7c63, + 0x7c6f, + 0x7c7a, + 0x7c86, + 0x7c92, + 0x7c9d, + 0x7ca9, + 0x7cb4, + 0x7cbf, + 0x7ccb, + 0x7cd6, + 0x7ce1, + 0x7cec, + 0x7cf7, + 0x7d02, + 0x7d0c, + 0x7d17, + 0x7d22, + 0x7d2c, + 0x7d37, + 0x7d41, + 0x7d4b, + 0x7d56, + 0x7d60, + 0x7d6a, + 0x7d74, + 0x7d7e, + 0x7d88, + 0x7d91, + 0x7d9b, + 0x7da5, + 0x7dae, + 0x7db8, + 0x7dc1, + 0x7dcb, + 0x7dd4, + 0x7ddd, + 0x7de6, + 0x7def, + 0x7df8, + 0x7e01, + 0x7e0a, + 0x7e13, + 0x7e1b, + 0x7e24, + 0x7e2c, + 0x7e35, + 0x7e3d, + 0x7e45, + 0x7e4d, + 0x7e56, + 0x7e5e, + 0x7e66, + 0x7e6d, + 0x7e75, + 0x7e7d, + 0x7e85, + 0x7e8c, + 0x7e94, + 0x7e9b, + 0x7ea3, + 0x7eaa, + 0x7eb1, + 0x7eb8, + 0x7ebf, + 0x7ec6, + 0x7ecd, + 0x7ed4, + 0x7edb, + 0x7ee1, + 0x7ee8, + 0x7eee, + 0x7ef5, + 0x7efb, + 0x7f01, + 0x7f08, + 0x7f0e, + 0x7f14, + 0x7f1a, + 0x7f20, + 0x7f25, + 0x7f2b, + 0x7f31, + 0x7f36, + 0x7f3c, + 0x7f41, + 0x7f47, + 0x7f4c, + 0x7f51, + 0x7f56, + 0x7f5b, + 0x7f60, + 0x7f65, + 0x7f6a, + 0x7f6f, + 0x7f74, + 0x7f78, + 0x7f7d, + 0x7f81, + 0x7f85, + 0x7f8a, + 0x7f8e, + 0x7f92, + 0x7f96, + 0x7f9a, + 0x7f9e, + 0x7fa2, + 0x7fa6, + 0x7fa9, + 0x7fad, + 0x7fb0, + 0x7fb4, + 0x7fb7, + 0x7fba, + 0x7fbe, + 0x7fc1, + 0x7fc4, + 0x7fc7, + 0x7fca, + 0x7fcc, + 0x7fcf, + 0x7fd2, + 0x7fd4, + 0x7fd7, + 0x7fd9, + 0x7fdc, + 0x7fde, + 0x7fe0, + 0x7fe2, + 0x7fe4, + 0x7fe6, + 0x7fe8, + 0x7fea, + 0x7fec, + 0x7fed, + 0x7fef, + 0x7ff1, + 0x7ff2, + 0x7ff3, + 0x7ff5, + 0x7ff6, + 0x7ff7, + 0x7ff8, + 0x7ff9, + 0x7ffa, + 0x7ffb, + 0x7ffb, + 0x7ffc, + 0x7ffd, + 0x7ffd, + 0x7ffe, + 0x7ffe, + 0x7ffe, + 0x7ffe, + 0x7ffe, + 0x7fff, +}; diff --git a/lib/ultralib/src/gu/sqrtf.s b/lib/ultralib/src/gu/sqrtf.s new file mode 100644 index 0000000..475a827 --- /dev/null +++ b/lib/ultralib/src/gu/sqrtf.s @@ -0,0 +1,25 @@ +/************************************************************************** + * * + * 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. * + * * + **************************************************************************/ + +/* + * Due to compiler bug, it won't insert a sqrt.s opcode in the stream so we + * make a function and call it for now. When compiler fixed, also remove the + * seperate Makefile rules + */ + +#include "sys/asm.h" +#include "sys/regdef.h" + +LEAF(sqrtf) + sqrt.s fv0, fa0 + j ra +END(sqrtf) diff --git a/lib/ultralib/src/gu/us2dex.c b/lib/ultralib/src/gu/us2dex.c new file mode 100644 index 0000000..cf977f9 --- /dev/null +++ b/lib/ultralib/src/gu/us2dex.c @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------- + $Id: us2dex.c,v 1.4 1998/10/09 06:15:30 has Exp $ + + File : us2dex.c + + Coded by Yoshitaka Yasumoto. Mar 19, 1997. + Copyright by Nintendo, Co., Ltd. 1997. + ---------------------------------------------------------------------*/ +#include <ultra64.h> +#include <PR/gs2dex.h> + +/* + * Routines that support processing of S2DEX microcode + */ + +/* + * guS2DInitBG + * Set BG screen draw parameters + * + * If called at time of initialization, then it only needs to be + * called again when changes made to imageFmt, imageSiz, imageLoad, * imageW, frameW. However, if imageLoad == G_BGLT_LOADBLOCK and * only frameW is changed, another call is unnecessary. + */ +void guS2DInitBg(uObjBg *bg) +{ + u16 tmemUse; + u16 shift; + u32 tsize; + + /* + * Get the useable volume for TMEM + * If imageFmt is CI then TLUT will use half + */ + tmemUse = (bg->b.imageFmt == G_IM_FMT_CI) ? 256 : 512; + + /* + * Get shift volume for conversion to TMEM word + */ + shift = 6 - bg->b.imageSiz; + + /* + * Set other parameters for Load Mode + */ + if (bg->b.imageLoad == G_BGLT_LOADBLOCK){ + bg->b.tmemW = bg->b.imageW >> shift; + bg->b.tmemH = (tmemUse / bg->b.tmemW) << 2; + bg->b.tmemSizeW = bg->b.tmemW << 1; + bg->b.tmemSize = bg->b.tmemH * bg->b.tmemSizeW; + bg->b.tmemLoadSH = (bg->b.tmemSize>>1) - 1; + bg->b.tmemLoadTH = GS_CALC_DXT(bg->b.tmemW); + } else { + bg->b.tmemW = (bg->b.frameW >> shift) + 3; + bg->b.tmemH = (tmemUse / bg->b.tmemW) << 2; + bg->b.tmemSizeW = (bg->b.imageW >> shift) * 2; + tsize = bg->b.tmemH * bg->b.tmemSizeW; + bg->b.tmemSize = tsize >> 16; + bg->b.tmemLoadSH = tsize & 0xffff; + bg->b.tmemLoadTH = bg->b.tmemH - 1; + } + return; +} + +/*======== End of us2dex.c ========*/ diff --git a/lib/ultralib/src/gu/us2dex2_emu.c b/lib/ultralib/src/gu/us2dex2_emu.c new file mode 100644 index 0000000..cc32179 --- /dev/null +++ b/lib/ultralib/src/gu/us2dex2_emu.c @@ -0,0 +1,12 @@ +/*---------------------------------------------------------------------* + Copyright (C) 1998, Nintendo. + + File us2dex2_emu.c + Coded by Yoshitaka Yasumoto. Apr 10, 1998. + + $Id: us2dex2_emu.c,v 1.3 1998/10/09 06:15:40 has Exp $ + *---------------------------------------------------------------------*/ +#define F3DEX_GBI_2 +#include "us2dex_emu.c" + +/*======== End of us2dex2_emu.c ========*/ diff --git a/lib/ultralib/src/gu/us2dex_emu.c b/lib/ultralib/src/gu/us2dex_emu.c new file mode 100644 index 0000000..e79ff7b --- /dev/null +++ b/lib/ultralib/src/gu/us2dex_emu.c @@ -0,0 +1,502 @@ +/*---------------------------------------------------------------------* + Copyright (C) 1998, Nintendo. + + File us2dex_emu.c + Coded by Yoshitaka Yasumoto. Apr 9, 1998. + + $Id: us2dex_emu.c,v 1.9 1999/07/08 05:02:04 yurugi Exp $ + *---------------------------------------------------------------------*/ +#define F3DEX_GBI +#include <ultra64.h> +#include <PR/gs2dex.h> + +#define RSP_DEBUG + +static u16 scissorX0 = 0; /* (s13.2) */ +static u16 scissorY0 = 0; /* (s13.2) */ +static u16 scissorX1 = 320<<2; /* (s13.2) */ +static u16 scissorY1 = 240<<2; /* (s13.2) */ +static u8 flagBilerp = 0; + +static u32 rdpSetTimg_w0, rdpSetTile_w0; +static u16 tmemSliceWmax; +static u16 imageSrcWsize; +static s16 flagSplit; +static u16 imagePtrX0; +static u32 imageTop; +static s16 tmemSrcLines; + +/* Addition 99/05/31(Y) */ +static s8 bgflg; + +/*----------------------------------------------------------------------------* + * Set scissoring parameters + * *---------------------------------------------------------------------------*/ +void guS2DEmuSetScissor(u32 ulx, u32 uly, u32 lrx, u32 lry, u8 flag) +{ + scissorX0 = (u16)ulx << 2; + scissorY0 = (u16)uly << 2; + scissorX1 = (u16)lrx << 2; + scissorY1 = (u16)lry << 2; + flagBilerp = (flag) ? 1 : 0; +} + +/*---------------------------------------------------------------------------* + * Create texture load RDP commands + *---------------------------------------------------------------------------*/ +static void tmemLoad_B(Gfx **pkt, u32 imagePtr, s16 loadLines, s16 tmemSH) +{ + /* + * Load 16-bit texture of tmemSH word width starting from imagePtr + * into the loadLines amount of lines of tmem. + */ + + /* [SetTImg] CMD=0x3d FMT=RGBA(0) SIZ=16b(2) */ + (*pkt)->words.w0 = rdpSetTimg_w0; + (*pkt)->words.w1 = imagePtr; + (*pkt) ++; + + /* [LoadSync] Wait for completion of preceding primitive draw */ + (*pkt)->words.w0 = (G_RDPLOADSYNC<<24); + (*pkt) ++; + + /* [LoadTile] CMD=0x34 TILE=7 SH=TMEMW*16-1 TMEMH*4-1 */ + (*pkt)->words.w0 = (G_LOADTILE<<24)|0x000000; +/* addition 99/5/31(Y) */ + if(bgflg==3) (*pkt)->words.w1 = 0x07000000 | (tmemSH-1)<<16; + else (*pkt)->words.w1 = 0x07000000 | (tmemSH-1)<<16 | (loadLines<<2)-1; + (*pkt) ++; +} + +static void tmemLoad_A(Gfx **pkt, u32 imagePtr, + s16 loadLines, s16 tmemAdrs, s16 tmemSH) +{ + /* + * Load 16-bit texture of tmemSH word width starting from imagePtr into + * the loadLines amount of lines of the tmemAdrs of tmem. + */ + + /* [TileSync] Wait for completion of Tile access of preceding command */ + (*pkt)->words.w0 = 0xe8000000; + (*pkt) ++; + + /* [SetTile] */ + (*pkt)->words.w0 = rdpSetTile_w0|tmemAdrs; + (*pkt)->words.w1 = 0x07000000; + (*pkt) ++; + + tmemLoad_B(pkt, imagePtr, loadLines, tmemSH); +} + +static void tmemLoad(Gfx **pkt, u32 *imagePtr, + s16 *imageRemain, s16 drawLines, s16 flagBilerp) +{ + s16 loadLines = drawLines + flagBilerp; + s16 iLoadable = (*imageRemain) - flagSplit; + + if (iLoadable >= loadLines){ /* If load can be done all at once */ + tmemLoad_B(pkt, *imagePtr, loadLines, tmemSliceWmax); + (*imagePtr) += imageSrcWsize * drawLines; + (*imageRemain) -= drawLines; + + } else { /* If load is to be partitioned */ + s16 SubSliceL2, SubSliceD2, SubSliceY2; + u32 imageTopSeg = imageTop & 0xff000000; + + SubSliceY2 = *imageRemain; + SubSliceL2 = loadLines - SubSliceY2; + SubSliceD2 = drawLines - SubSliceY2; + + if (SubSliceL2 > 0){ + u32 imagePtr2; + + imagePtr2 = imageTop + imagePtrX0; + if (SubSliceY2 & 1){ + imagePtr2 -= imageSrcWsize; + imagePtr2 = imageTopSeg | (imagePtr2 & 0x00ffffff); /*Segment counterm */ + SubSliceY2 --; + SubSliceL2 ++; + } + tmemLoad_A(pkt, imagePtr2, + SubSliceL2, SubSliceY2 * tmemSliceWmax, tmemSliceWmax); + } + if (flagSplit){ + u32 imagePtr1A, imagePtr1B; + s16 SubSliceY1, SubSliceL1; + s16 tmemSH_A, tmemSH_B; + + imagePtr1A = (*imagePtr) + iLoadable * imageSrcWsize; + imagePtr1B = imageTop; + SubSliceY1 = iLoadable; + if (SubSliceL1 = iLoadable & 1){ + imagePtr1A -= imageSrcWsize; + imagePtr1B -= imageSrcWsize; + imagePtr1B = imageTopSeg | (imagePtr1B & 0x00ffffff); /*Segment countermeasure */ + SubSliceY1 --; + } + SubSliceL1 ++; + tmemSH_A = (imageSrcWsize - imagePtrX0) >> 3; + tmemSH_B = tmemSliceWmax - tmemSH_A; + tmemLoad_A(pkt, imagePtr1B, + SubSliceL1, SubSliceY1 * tmemSliceWmax + tmemSH_A, tmemSH_B); + tmemLoad_A(pkt, imagePtr1A, + SubSliceL1, SubSliceY1 * tmemSliceWmax, tmemSH_A); + } + if (iLoadable > 0){ + + tmemLoad_A(pkt, *imagePtr, iLoadable, 0, tmemSliceWmax); + + } else { + + /* [SetTile] */ + (*pkt)->words.w0 = rdpSetTile_w0; + (*pkt)->words.w1 = 0x07000000; + (*pkt) ++; + } + + (*imageRemain) -= drawLines; + if ((*imageRemain) > 0){ + (*imagePtr) += imageSrcWsize * drawLines; + } else { + (*imageRemain) = tmemSrcLines - SubSliceD2; + (*imagePtr) = imageTop + SubSliceD2 * imageSrcWsize + imagePtrX0; + } + + } +} + +/*---------------------------------------------------------------------------* + * Scalable BG serface draw process + *---------------------------------------------------------------------------*/ +void guS2DEmuBgRect1Cyc(Gfx **pkt, uObjBg *bg) +{ + s16 frameX0, frameX1, framePtrY0, frameRemain; + s16 imageX0, imageY0, imageSliceW, imageW; + s32 imageYorig; + s16 scaleW, scaleH; + + s16 imageSrcW, imageSrcH; + s16 tmemSliceLines, imageSliceLines; + s32 frameSliceLines, frameSliceCount; + u16 imageS, imageT; + u32 imagePtr; + + s16 imageISliceL0, imageIY0; + s32 frameLSliceL0; + + scaleW = bg->s.scaleW; + scaleH = bg->s.scaleH; + +/* addition 99/05/31(Y) */ + bgflg=bg->s.imageSiz; + if(scaleW==0) scaleW=1; + if(scaleH==0) scaleH=1; + + +{ + /*-------------------------------------------------* + Scissoring process + *-------------------------------------------------*/ + /* + / frameX0, frameX1, framePtrY0, frameRemain + / imageX0, imageY0, tmemSliceW + / imageSrcW, imageSrcH + */ + s16 pixX0, pixY0, pixX1, pixY1; /* (s13.2) */ + s16 frameY0, frameW, frameH; + s32 frameWmax, frameHmax; + + /* Determine maximum frame size from image and enlargement ratio */ + frameWmax = ((((s32)bg->s.imageW << 10) / scaleW)-1) & ~3; + frameHmax = ((((s32)bg->s.imageH << 10) / scaleH)-1) & ~3; + + /* Clamp the frame size */ + frameW = bg->s.frameW; + frameH = bg->s.frameH; + frameX0 = bg->s.frameX; + frameY0 = bg->s.frameY; + if ((frameWmax = bg->s.frameW - frameWmax) < 0) frameWmax = 0; + if ((frameHmax = bg->s.frameH - frameHmax) < 0) frameHmax = 0; + frameW -= frameWmax; + frameH -= frameHmax; + if (bg->s.imageFlip & G_BG_FLAG_FLIPS){ + frameX0 += frameWmax; + } + + /* Caluculate amount of projection from screen */ + pixX0 = scissorX0 - frameX0; /* (s13.2) */ + pixY0 = scissorY0 - frameY0; /* (s13.2) */ + pixX1 = frameW - scissorX1 + frameX0; /* (s13.2) */ + pixY1 = frameH - scissorY1 + frameY0; /* (s13.2) */ + + /* Clamp if no projection */ + if (pixX0 < 0) pixX0 = 0; + if (pixY0 < 0) pixY0 = 0; + if (pixX1 < 0) pixX1 = 0; + if (pixY1 < 0) pixY1 = 0; + + /* Cut the part that is projecting */ + frameW = frameW - (pixX0 + pixX1); /* (s13.2) */ + frameH = frameH - (pixY0 + pixY1); /* (s13.2) */ + frameX0 = frameX0 + pixX0; /* (s13.2) */ + frameY0 = frameY0 + pixY0; /* (s13.2) */ + + /* Terminate if no draw range remains */ + if (frameW <= 0 || frameH <= 0) return; + + /* Caluculate frame */ + frameX1 = frameX0 + frameW; /* (s13.2) */ + framePtrY0 = frameY0 >> 2; /* (s15.0) */ + frameRemain = frameH >> 2; /* (s15.0) */ + + /* Join image columns */ + imageSrcW = bg->s.imageW << 3; /* (u11.5) */ + imageSrcH = bg->s.imageH << 3; /* (u11.5) */ + + /* Get image range (u14.2)*(u6.10)=(u20.12)->(u11.5) */ + imageSliceW = (imageW = frameW * scaleW >> 7) + flagBilerp * 32; + if (bg->s.imageFlip & G_BG_FLAG_FLIPS){ + imageX0 = bg->s.imageX + (pixX1 * scaleW >> 7); /* (s10.5) */ + } else { + imageX0 = bg->s.imageX + (pixX0 * scaleW >> 7); /* (s10.5) */ + } + imageY0 = bg->s.imageY + (pixY0 * scaleH >> 7); /* (s10.5) */ + imageYorig = bg->s.imageYorig; + + /* Loop one step down when left end of image area is greater than right end of image source */ + while (imageX0 >= imageSrcW){ + imageX0 -= imageSrcW; + imageY0 += 32; + imageYorig += 32; /* Add 1 to carrier */ + } + + /* Loop when top end of image area is greater than bottom end of image source */ + while (imageY0 >= imageSrcH){ + imageY0 -= imageSrcH; + imageYorig -= imageSrcH; + } +} + +{ + /*-------------------------------------------------* + Check process connecting top and bottom of image + *-------------------------------------------------*/ + /* + // flagSplit + // tmemSrcLines + // imageSrcLines + */ + /* Top/bottom connection process necessary when image range straddles right +end */ + flagSplit = (imageX0 + imageSliceW >= imageSrcW); + + /* Number of image lines that can be loaded at once */ + tmemSrcLines = imageSrcH >> 5; +} + +{ + /*-------------------------------------------------* + Get load data for TMEM + *-------------------------------------------------*/ + /* + //Calculate number of lines that can be loaded into TMEM. + // If the slice width changes due to scissoring and the linked + // load line number is changed, then the frame division line will + // change and the result will be the generation of unnatural wrinkles. + // To prevent this, the division region is set such that scissoring + // does not occur. + // + */ + s16 tmemSize, tmemMask, tmemShift; + s32 imageNumSlice; + s32 imageSliceWmax; + s32 imageLYoffset, frameLYoffset; + s32 imageLHidden, frameLHidden; + s32 frameLYslice; + + static s16 TMEMSIZE[] = { 512, 512, 256, 512, 512 }; + static s16 TMEMMASK[] = { 0x1ff, 0xff, 0x7f, 0x3f }; + static s16 TMEMSHIFT[] = { 0x200, 0x100, 0x80, 0x40 }; + tmemSize = TMEMSIZE[bg->s.imageFmt]; /* (s15.0) */ + tmemMask = TMEMMASK[bg->s.imageSiz]; /* (s10.5) */ + tmemShift = TMEMSHIFT[bg->s.imageSiz]; /* (s10.5)->(s15.0) */ + + /* Calculate tmem width to accommodate the slice image width */ + /* o Extra is needed at Bilerp time. + // o Clamp slice image width based on image source width. + // o Cut image width end number at TMEM Word boundary. + // o tmem width + 1 when start position not in agreement with Word boundary */ +/* addition 99/05/31(Y) */ + if(bgflg==3){ + tmemSize=480; + imageSliceWmax = 0x2800; + } + else{ + imageSliceWmax = (((s32)bg->s.frameW * (s32)scaleW)>>7) + (flagBilerp<<5); + if (imageSliceWmax > imageSrcW) imageSliceWmax = imageSrcW; + } + tmemSliceWmax = (imageSliceWmax + tmemMask) / tmemShift + 1; + + /* Get TMEM/image/frame line number that can be loaded at once */ + tmemSliceLines = tmemSize / tmemSliceWmax; /* (s15.0) */ + imageSliceLines = tmemSliceLines - flagBilerp; /* (s15.0) */ + frameSliceLines = (imageSliceLines << 20) / scaleH; /* (s21.10) */ + + /* Line up image Y coordinate offset value with frame image */ + imageLYoffset = ((s32)imageY0 - imageYorig) << 5; + if (imageLYoffset < 0) imageLYoffset -= (scaleH - 1); + frameLYoffset = imageLYoffset / scaleH; + frameLYoffset <<= 10; + + /* Get slice number corresponding to image Y */ + if (frameLYoffset >= 0){ + imageNumSlice = frameLYoffset / frameSliceLines; + } else { + imageNumSlice = (frameLYoffset - frameSliceLines + 1) / frameSliceLines; + } + + /* Calculate extent to which first draw slice is hidden at top of frame */ + frameLYslice = (frameLSliceL0 = frameSliceLines * imageNumSlice) & ~1023; + frameLHidden = frameLYoffset - frameLYslice; + imageLHidden = (frameLHidden >> 10) * scaleH; + + /* Calculate fram size of first draw slice */ + frameLSliceL0 = (frameLSliceL0 & 1023) + frameSliceLines - frameLHidden; + + /* Calculate image parameters for draw in midst of slice */ + imageT = (imageLHidden >> 5) & 31; + imageLHidden >>= 10; + imageISliceL0 = imageSliceLines - imageLHidden; + imageIY0 = + imageSliceLines * imageNumSlice + (imageYorig & ~31) / 32 + imageLHidden; + if (imageIY0 < 0) imageIY0 += (bg->s.imageH >> 2); + if (imageIY0 >= (bg->s.imageH >> 2)) imageIY0 -= (bg->s.imageH >> 2); + imageTop = (u32)bg->s.imagePtr; /* (u32.0) */ + imageSrcWsize = (imageSrcW / tmemShift) << 3; /* (u16.0) */ + imagePtrX0 = (imageX0 / tmemShift) << 3; /* (u16.0) */ + imagePtr = imageTop + imageSrcWsize * imageIY0 + imagePtrX0; + + /* S invert process */ + imageS = imageX0 & tmemMask; /* (u10.5) */ + if (bg->s.imageFlip & G_BG_FLAG_FLIPS){ + imageS = - (imageS + imageW); + } +} + +{ + /*-------------------------------------------------* + Creating RDP command constant values + *-------------------------------------------------*/ + /* u32 rdpSetTimg_w0; + u32 rdpSetTile_w0; */ +/* Addition 99/05/31(Y) */ + if(bgflg==3){ + rdpSetTimg_w0 = (G_SETTIMG<<24)+0x180000+(imageSrcWsize>>1)-1; + rdpSetTile_w0 = (G_SETTILE<<24)+0x180000+(tmemSliceWmax<<9); + } + else{ + rdpSetTimg_w0 = (G_SETTIMG<<24)+0x100000+(imageSrcWsize>>1)-1; + rdpSetTile_w0 = (G_SETTILE<<24)+0x100000+(tmemSliceWmax<<9); + } + /* [SetTile:7] */ + (*pkt)->words.w0 = rdpSetTile_w0; + (*pkt)->words.w1 = 0x07000000; + (*pkt)++; + /* [SetTile:0] */ + (*pkt)->words.w0 = rdpSetTile_w0; + ((u8 *)&((*pkt)->words.w0))[1] = (bg->s.imageFmt<<5)|(bg->s.imageSiz<<3); + (*pkt)->words.w1 = 0x0007c1f0 | (bg->s.imagePal<<20); + (*pkt)++; + /* [SetTileSize:7] */ + (*pkt)->words.w0 = (G_SETTILESIZE<<24)|0x000000; + (*pkt)->words.w1 = 0x00000000; + (*pkt)++; +} + +{ + s16 imageRemain; + s16 imageSliceH, frameSliceH; + + imageRemain = tmemSrcLines - imageIY0; + imageSliceH = imageISliceL0; + frameSliceCount = frameLSliceL0; + + while(1){ + + /* Calculate draw line number and determine whether to perform a draw */ + frameSliceH = frameSliceCount >> 10; + if (frameSliceH <= 0){ + /* If no draw to be performed */ + imageRemain -= imageSliceH; + if (imageRemain > 0){ + imagePtr += imageSrcWsize * imageSliceH; + } else { + imagePtr = imageTop - (imageRemain * imageSrcWsize) + imagePtrX0; + imageRemain += tmemSrcLines; + } + + } else { + /* If draw to be performed */ + s16 framePtrY1; + + frameSliceCount &= 1023; + if ((frameRemain -= frameSliceH) < 0){ + /* Determine final slice */ + frameSliceH += frameRemain; + imageSliceH += ((frameRemain * scaleH) >> 10) + 1; + if (imageSliceH > imageSliceLines) imageSliceH = imageSliceLines; + } + tmemLoad(pkt, &imagePtr, &imageRemain, imageSliceH, flagBilerp); + + /* Get draw frame range */ + framePtrY1 = framePtrY0 + frameSliceH; /* (s15.0) */ + + /* [PipeSync] Wait for end of preceding LOADTILE command */ + (*pkt)->words.w0 = (G_RDPPIPESYNC<<24); + (*pkt) ++; + + /* Rectangle draw */ + /* Here an RSP command is created. With ucode an RDP command is created */ +#if 1 + { + /* [TextureRectangle] */ + (*pkt)->words.w0 = (G_TEXRECT<<24)|(frameX1<<12)|(framePtrY1<<2); + (*pkt)->words.w1 = (frameX0<<12)|(framePtrY0<<2); + (*pkt) ++; +#else + /* Code for checking slice division line */ + if (frameSliceH > 1){ + (*pkt)->words.w0 = (G_TEXRECT<<24)|(frameX1<<12)|(framePtrY1<<2)-4; + (*pkt)->words.w1 = (frameX0<<12)|(framePtrY0<<2); + (*pkt) ++; +#endif + +#if 0 /* At RDP command creation time */ + (*pkt)->words.w0 = (imageS<<16) | imageT; + (*pkt)->words.w1 = (scaleW<<16) | scaleH; +#else /* At RSP command creation time */ + (*pkt)->words.w0 = (G_RDPHALF_1<<24); + (*pkt)->words.w1 = (imageS<<16) | imageT; + (*pkt) ++; + (*pkt)->words.w0 = (G_RDPHALF_2<<24); + (*pkt)->words.w1 = (scaleW<<16) | scaleH; +#endif + (*pkt) ++; + } + + /* Update region */ + framePtrY0 = framePtrY1; + + /* End if no more undrawn line numbers for frame */ + if (frameRemain <= 0){ + return; + } + } + frameSliceCount += frameSliceLines; + imageSliceH = imageSliceLines; + imageT = 0; + } +} +} + +/*======== End of us2dex_emu.c ========*/ diff --git a/lib/ultralib/src/gu/usprite.c b/lib/ultralib/src/gu/usprite.c new file mode 100644 index 0000000..a10ed34 --- /dev/null +++ b/lib/ultralib/src/gu/usprite.c @@ -0,0 +1,39 @@ + +/************************************************************************** + * * + * Copyright (C) 1996, 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 "gbi.h" + +void guSprite2DInit(uSprite *SpritePointer, + void *SourceImagePointer, + void *TlutPointer, + short Stride, + short SubImageWidth, + short SubImageHeight, + char SourceImageType, + char SourceImageBitSize, + short SourceImageOffsetS, + short SourceImageOffsetT) +{ + SpritePointer->s.SourceImagePointer = SourceImagePointer; + SpritePointer->s.TlutPointer = TlutPointer; + SpritePointer->s.Stride = Stride; + SpritePointer->s.SubImageWidth = SubImageWidth; + SpritePointer->s.SubImageHeight = SubImageHeight; + SpritePointer->s.SourceImageType = SourceImageType; + SpritePointer->s.SourceImageBitSize = SourceImageBitSize; + SpritePointer->s.SourceImageOffsetS = SourceImageOffsetS; + SpritePointer->s.SourceImageOffsetT = SourceImageOffsetT; +} + + + diff --git a/lib/ultralib/src/host/host_ptn64.c b/lib/ultralib/src/host/host_ptn64.c new file mode 100644 index 0000000..9e6fbd6 --- /dev/null +++ b/lib/ultralib/src/host/host_ptn64.c @@ -0,0 +1,203 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../io/piint.h" + +#include "macros.h" + +static volatile unsigned int* ptwtmode = (unsigned*)0xbff08014; +static volatile unsigned int* ptstat = (unsigned*)0xbff08004; +static volatile unsigned int* ptport = (unsigned*)0xbff08000; +static volatile unsigned int* n64piok = (unsigned*)PHYS_TO_K1(PI_STATUS_REG); + +static OSMesgQueue waitPtQueue; +static OSMesg waitPtQueueBuf; +static u32 isWaitPtQueueCreated = FALSE; + +static void createWaitPtQueue(void) { + osCreateMesgQueue(&waitPtQueue, &waitPtQueueBuf, 1); + isWaitPtQueueCreated = TRUE; +} + +static u32 getPT_wait(void) { + OSTimer waitTimer; + u32 status UNUSED; + + for (;;) { + while (*n64piok & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + ; + } + + if (*ptstat & 2) { + return *ptport; + } + __osPiRelAccess(); + + osRecvMesg(&waitPtQueue, NULL, OS_MESG_NOBLOCK); + osSetTimer(&waitTimer, OS_USEC_TO_CYCLES(1000), 0, &waitPtQueue, NULL); + osRecvMesg(&waitPtQueue, NULL, OS_MESG_BLOCK); + + __osPiGetAccess(); + } +} + +static void putPT(u32 c) { + while (*n64piok & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + ; + } + while (!(*ptstat & 4)) { + ; + } + *ptport = c; +} + +static u32 getPT(void) { + while (*n64piok & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + ; + } + while (!(*ptstat & 2)) { + ; + } + return *ptport; +} + +void osReadHost_pt(void* dramAddr, u32 nbytes) { + u8 * tPtr; + u32 buf[256]; + u32 * bp; + u32 data; + u32 ct; + u32 ct1; + u32 ct1_bak; + u32 shift; + u32 cmd; + u32 size; + + if (nbytes == 0) { + return; + } + + if (!isWaitPtQueueCreated) { + createWaitPtQueue(); + } + + __osPiGetAccess(); + + putPT(0x82U); + + cmd = getPT_wait(); + + size = getPT(); + + if (cmd != 2) { + nbytes = -1U; + } + + putPT(nbytes); + + if (size != nbytes) { + goto osReadHost_ret; + } + + tPtr = dramAddr; + ct = nbytes / 4; + + while (ct != 0) { + if (ct > 0x100) { + ct1 = 0x100; + ct1_bak = 0x100; + ct -= 0x100; + } else { + ct1_bak = ct1 = ct; + ct = 0; + } + bp = &buf; + + while (ct1 != 0) { + *(bp++) = getPT(); + ct1--; + } + + memcpy(tPtr, &buf, ct1_bak * 4); + tPtr += ct1_bak * 4; + } + + nbytes &= 3; + + if (nbytes != 0) { + data = getPT(); + shift = 0x18; + + do { + *(tPtr++) = (data >> shift); + nbytes--; + shift -= 8; + } while (nbytes != 0); + } + +osReadHost_ret: + __osPiRelAccess(); + return; +} + +void osWriteHost_pt(void* dramAddr, u32 nbytes) { + u8 *tPtr; + u32 buf[256]; + u32 *bp; + u32 ct; + u32 ct1; + u32 ct1_bak; + u32 cmd; + u32 size; + + if (nbytes == 0) { + return; + } + + if (!isWaitPtQueueCreated) { + createWaitPtQueue(); + } + + __osPiGetAccess(); + putPT(0x82); + + cmd = getPT_wait(); + + size = getPT(); + + if (cmd != 3) { + nbytes = -1; + } + + putPT(nbytes); + + if (size != nbytes) { + goto osWriteHost_ret; + } + + tPtr = dramAddr; + ct = (nbytes + 3) >> 2; + + while (ct != 0) { + if (ct > 0x100) { + ct1 = 0x100; + ct1_bak = 0x100; + ct -= 0x100; + } else { + ct1_bak = ct1 = ct; + ct = 0; + } + + memcpy(bp = buf, tPtr, ct1_bak * 4); + + while (ct1 != 0) { + putPT(*(bp++)); + ct1--; + } + + tPtr += ct1_bak * 4; + } + +osWriteHost_ret: + __osPiRelAccess(); + return; +} diff --git a/lib/ultralib/src/host/readhost.c b/lib/ultralib/src/host/readhost.c new file mode 100644 index 0000000..5cc1974 --- /dev/null +++ b/lib/ultralib/src/host/readhost.c @@ -0,0 +1,36 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rdb.h" + +#include "macros.h" + +u32 __osRdb_Read_Data_Buf; +u32 __osRdb_Read_Data_Ct; + +static int readHostInitialized = FALSE; +static OSMesgQueue readHostMesgQueue; +static OSMesg readHostMesgBuf[1]; + +void osReadHost(void* dramAddr, u32 nbytes) { + char tstr[4]; + u32 sent = 0; + + if (!readHostInitialized) { + osCreateMesgQueue(&readHostMesgQueue, readHostMesgBuf, ARRLEN(readHostMesgBuf)); + osSetEventMesg(OS_EVENT_RDB_READ_DONE, &readHostMesgQueue, NULL); + readHostInitialized = TRUE; + } + + __osRdb_Read_Data_Buf = dramAddr; + __osRdb_Read_Data_Ct = nbytes; + + while (sent == 0) { + sent += __osRdbSend(tstr, 1, RDB_TYPE_GtoH_READY_FOR_DATA); + } + + osRecvMesg(&readHostMesgQueue, NULL, OS_MESG_BLOCK); + return; +} + +#endif diff --git a/lib/ultralib/src/host/writehost.c b/lib/ultralib/src/host/writehost.c new file mode 100644 index 0000000..92e9587 --- /dev/null +++ b/lib/ultralib/src/host/writehost.c @@ -0,0 +1,54 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rdb.h" + +#include "macros.h" + +static int writeHostInitialized = FALSE; +static OSMesgQueue writeHostMesgQueue; +static OSMesg writeHostMesgBuf[1]; + +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) + +void osWriteHost(void * dramAddr, u32 nbytes) { + u8* tPtr = dramAddr; + u32 sent; + u8 dCount[3]; + u32 count; + + if (nbytes == 0) { + __osError(73, 1, nbytes); + return; + } + + if (writeHostInitialized == FALSE) { + osCreateMesgQueue(&writeHostMesgQueue, writeHostMesgBuf, ARRLEN(writeHostMesgBuf)); + osSetEventMesg(OS_EVENT_RDB_DATA_DONE, &writeHostMesgQueue, NULL); + writeHostInitialized = TRUE; + } + + while (nbytes != 0) { + count = MIN(nbytes, 0x8000); + + dCount[0] = (count & 0xFF0000) >> 0x10; + dCount[1] = (count & 0xFF00) >> 8; + dCount[2] = count & 0xFF; + + sent = 0; + while (sent < ARRLEN(dCount)) { + sent += __osRdbSend(dCount + sent, ARRLEN(dCount) - sent, RDB_TYPE_GtoH_DATA_CT); + } + + sent = 0; + while (sent < count) { + sent += __osRdbSend(tPtr + sent, count - sent, RDB_TYPE_GtoH_DATA); + } + + nbytes -= count; + tPtr += count; + osRecvMesg(&writeHostMesgQueue, NULL, OS_MESG_BLOCK); + } +} + +#endif diff --git a/lib/ultralib/src/io/ai.c b/lib/ultralib/src/io/ai.c new file mode 100755 index 0000000..5e345dc --- /dev/null +++ b/lib/ultralib/src/io/ai.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osAiDeviceBusy(void) { + register s32 status = IO_READ(AI_STATUS_REG); + + if (status & AI_STATUS_FIFO_FULL) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/ultralib/src/io/aigetlen.c b/lib/ultralib/src/io/aigetlen.c new file mode 100755 index 0000000..6b83682 --- /dev/null +++ b/lib/ultralib/src/io/aigetlen.c @@ -0,0 +1,8 @@ +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 osAiGetLength(void) { + return IO_READ(AI_LEN_REG); +} diff --git a/lib/ultralib/src/io/aigetstat.c b/lib/ultralib/src/io/aigetstat.c new file mode 100755 index 0000000..c7a3cf7 --- /dev/null +++ b/lib/ultralib/src/io/aigetstat.c @@ -0,0 +1,8 @@ +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 osAiGetStatus() { + return IO_READ(AI_STATUS_REG); +} diff --git a/lib/ultralib/src/io/aisetfreq.c b/lib/ultralib/src/io/aisetfreq.c new file mode 100755 index 0000000..52cd8c3 --- /dev/null +++ b/lib/ultralib/src/io/aisetfreq.c @@ -0,0 +1,29 @@ +#include "PR/rcp.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osAiSetFrequency(u32 frequency) { + register unsigned int dacRate; + register unsigned char bitRate; + register float f; + + f = osViClock / (float)frequency + .5f; + dacRate = f; + + if (dacRate < AI_MIN_DAC_RATE) { + return -1; + } + + bitRate = dacRate / 66; + + 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; +} diff --git a/lib/ultralib/src/io/aisetnextbuf.c b/lib/ultralib/src/io/aisetnextbuf.c new file mode 100755 index 0000000..d4295d3 --- /dev/null +++ b/lib/ultralib/src/io/aisetnextbuf.c @@ -0,0 +1,31 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osAiSetNextBuffer(void *bufPtr, u32 size) { + static u8 hdwrBugFlag = FALSE; + char *bptr; + + if (__osAiDeviceBusy()) { + return -1; + } + + bptr = bufPtr; + + if (hdwrBugFlag) { + bptr -= 0x2000; + } + + if ((((u32)bufPtr + size) & 0x1fff) == 0) { + hdwrBugFlag = TRUE; + } else { + hdwrBugFlag = FALSE; + } + + IO_WRITE(AI_DRAM_ADDR_REG, osVirtualToPhysical(bptr)); + IO_WRITE(AI_LEN_REG, size); + return 0; +} diff --git a/lib/ultralib/src/io/cartrominit.c b/lib/ultralib/src/io/cartrominit.c new file mode 100644 index 0000000..9cd1617 --- /dev/null +++ b/lib/ultralib/src/io/cartrominit.c @@ -0,0 +1,65 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "PR/R4300.h" +#include "PR/rcp.h" + +OSPiHandle __CartRomHandle ALIGNED(8); +OSPiHandle *osCartRomInit(void) +{ + u32 value; + u32 saveMask; + static int first = 1; + register u32 stat; + u32 latency; + u32 pulse; + u32 pageSize; + u32 relDuration; + + __osPiGetAccess(); + + if (!first) { + __osPiRelAccess(); + return &__CartRomHandle; + } + + first = 0; + __CartRomHandle.type = DEVICE_TYPE_CART; + __CartRomHandle.baseAddress = PHYS_TO_K1(PI_DOM1_ADDR2); + __CartRomHandle.domain = PI_DOMAIN1; + __CartRomHandle.speed = 0; + + bzero(&__CartRomHandle.transferInfo, sizeof(__OSTranxInfo)); + + while (stat = IO_READ(PI_STATUS_REG), stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + ; + } + + latency = IO_READ(PI_BSD_DOM1_LAT_REG); + pageSize = IO_READ(PI_BSD_DOM1_PGS_REG); + relDuration = IO_READ(PI_BSD_DOM1_RLS_REG); + pulse = IO_READ(PI_BSD_DOM1_PWD_REG); + + IO_WRITE(PI_BSD_DOM1_LAT_REG, 0xFF); + IO_WRITE(PI_BSD_DOM1_PGS_REG, 0); + IO_WRITE(PI_BSD_DOM1_RLS_REG, 3); + IO_WRITE(PI_BSD_DOM1_PWD_REG, 0xFF); + + value = IO_READ(__CartRomHandle.baseAddress); + __CartRomHandle.latency = value & 0xFF; + __CartRomHandle.pageSize = (value >> 0x10) & 0xF; + __CartRomHandle.relDuration = (value >> 0x14) & 0xF; + __CartRomHandle.pulse = (value >> 8) & 0xFF; + + IO_WRITE(PI_BSD_DOM1_LAT_REG, latency); + IO_WRITE(PI_BSD_DOM1_PGS_REG, pageSize); + IO_WRITE(PI_BSD_DOM1_RLS_REG, relDuration); + IO_WRITE(PI_BSD_DOM1_PWD_REG, pulse); + + saveMask = __osDisableInt(); + __CartRomHandle.next = __osPiTable; + __osPiTable = &__CartRomHandle; + __osRestoreInt(saveMask); + __osPiRelAccess(); + + return &__CartRomHandle; +} diff --git a/lib/ultralib/src/io/contchannelreset.c b/lib/ultralib/src/io/contchannelreset.c new file mode 100644 index 0000000..d209ffc --- /dev/null +++ b/lib/ultralib/src/io/contchannelreset.c @@ -0,0 +1,27 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 __osContChannelReset(OSMesgQueue* mq, int channel) { + s32 i; + s32 ret; + u8* ptr = (u8*)&__osPfsPifRam; + + __osSiGetAccess(); + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + for (i = 0; i < channel; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + + *ptr++ = CONT_CMD_CHANNEL_RESET; + *ptr = CONT_CMD_END; + + ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osSiRelAccess(); + return ret; +} diff --git a/lib/ultralib/src/io/conteeplongread.c b/lib/ultralib/src/io/conteeplongread.c new file mode 100755 index 0000000..15af27c --- /dev/null +++ b/lib/ultralib/src/io/conteeplongread.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osEepromLongRead(OSMesgQueue *mq, u8 address, u8 *buffer, int length) { + s32 ret = 0; + + while (length > 0) { + ERRCK(osEepromRead(mq, address, buffer)); + length -= EEPROM_BLOCK_SIZE; + address++; + buffer += EEPROM_BLOCK_SIZE; + } + + return ret; +} diff --git a/lib/ultralib/src/io/conteeplongwrite.c b/lib/ultralib/src/io/conteeplongwrite.c new file mode 100755 index 0000000..ea92431 --- /dev/null +++ b/lib/ultralib/src/io/conteeplongwrite.c @@ -0,0 +1,17 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osEepromLongWrite(OSMesgQueue *mq, u8 address, u8 *buffer, int length) { + s32 ret = 0; + + while (length > 0) { + ERRCK(osEepromWrite(mq, address, buffer)); + length -= EEPROM_BLOCK_SIZE; + address++; + buffer += EEPROM_BLOCK_SIZE; + osSetTimer(&__osEepromTimer, 562500, 0, &__osEepromTimerQ, &__osEepromTimerMsg); + osRecvMesg(&__osEepromTimerQ, NULL, OS_MESG_BLOCK); + } + + return ret; +} diff --git a/lib/ultralib/src/io/conteepprobe.c b/lib/ultralib/src/io/conteepprobe.c new file mode 100755 index 0000000..d24ff06 --- /dev/null +++ b/lib/ultralib/src/io/conteepprobe.c @@ -0,0 +1,32 @@ +#include "controller.h" +#include "siint.h" + +s32 osEepromProbe(OSMesgQueue *mq) { + s32 ret = 0; + u16 type; + OSContStatus sdata; + + __osSiGetAccess(); + ret = __osEepStatus(mq, &sdata); + type = sdata.type & (CONT_EEPROM | CONT_EEP16K); + + if (ret != 0) { + ret = 0; + } else { + switch (type) { + case CONT_EEPROM: + ret = EEPROM_TYPE_4K; + break; + case CONT_EEPROM | CONT_EEP16K: + ret = EEPROM_TYPE_16K; + break; + default: + ret = 0; + break; + } + } + + __osEepromRead16K = 0; + __osSiRelAccess(); + return ret; +} diff --git a/lib/ultralib/src/io/conteepread.c b/lib/ultralib/src/io/conteepread.c new file mode 100755 index 0000000..887ada6 --- /dev/null +++ b/lib/ultralib/src/io/conteepread.c @@ -0,0 +1,100 @@ +#include "macros.h" +#include "PR/rcp.h" +#include "controller.h" +#include "siint.h" + +static void __osPackEepReadData(u8 address); +OSPifRam __osEepPifRam ALIGNED(16); +s32 __osEepromRead16K; + +s32 osEepromRead(OSMesgQueue *mq, u8 address, u8 *buffer) +{ + s32 ret = 0; + int i = 0; + u16 type; + u8 *ptr; + OSContStatus sdata; + __OSContEepromFormat eepromformat; + + ptr = (u8 *)&__osEepPifRam.ramarray; + __osSiGetAccess(); + ret = __osEepStatus(mq, &sdata); + type = sdata.type & (CONT_EEPROM | CONT_EEP16K); + + if (ret != 0) { + __osSiRelAccess(); + return ret; + } + + switch (type) { + case CONT_EEPROM: + if (address >= EEPROM_MAXBLOCKS) { + ret = CONT_RANGE_ERROR; + } + break; + case CONT_EEPROM | CONT_EEP16K: + __osEepromRead16K = 1; + if (address >= EEP16K_MAXBLOCKS) { + //not technically possible + ret = CONT_RANGE_ERROR; + } + break; + default: + ret = CONT_NO_RESPONSE_ERROR; + break; + } + + if (ret != 0) { + __osSiRelAccess(); + return ret; + } + + 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); + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); //recv response + __osContLastCmd = CONT_CMD_READ_EEPROM; + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + for (i = 0; i < MAXCONTROLLERS; 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 = (u8 *)&__osEepPifRam.ramarray; + __OSContEepromFormat eepromformat; + int i; + + __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 < MAXCONTROLLERS; i++) { + *ptr++ = 0; + } + + *(__OSContEepromFormat *)(ptr) = eepromformat; + ptr += sizeof(__OSContEepromFormat); + ptr[0] = CONT_CMD_END; +} diff --git a/lib/ultralib/src/io/conteepwrite.c b/lib/ultralib/src/io/conteepwrite.c new file mode 100755 index 0000000..aa351fd --- /dev/null +++ b/lib/ultralib/src/io/conteepwrite.c @@ -0,0 +1,158 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "controller.h" +#include "siint.h" + +static void __osPackEepWriteData(u8 address, u8 *buffer); +s32 osEepromWrite(OSMesgQueue *mq, u8 address, u8 *buffer) +{ + s32 ret = 0; + u16 type; + u8 *ptr = (u8 *)&__osEepPifRam.ramarray; + __OSContEepromFormat eepromformat; + OSContStatus sdata; + u8 temp[8]; + + __osSiGetAccess(); + ret = __osEepStatus(mq, &sdata); + + type = sdata.type & (CONT_EEPROM | CONT_EEP16K); + + if (ret != 0) { + __osSiRelAccess(); + return ret; + } + + switch (type) { + case CONT_EEPROM: + if (address >= EEPROM_MAXBLOCKS) { + ret = CONT_RANGE_ERROR; + } + break; + case CONT_EEPROM | CONT_EEP16K: + if (address >= EEP16K_MAXBLOCKS) { + //not technically possible + ret = CONT_RANGE_ERROR; + } + if (__osEepromRead16K) + { + __osEepromRead16K = 0; + __osSiRelAccess(); + osEepromRead(mq, (address ^ 1), temp); + __osSiGetAccess(); + } + break; + default: + ret = CONT_NO_RESPONSE_ERROR; + break; + } + + if (ret != 0) { + __osSiRelAccess(); + return ret; + } + + 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); + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); //recv response + __osContLastCmd = CONT_CMD_WRITE_EEPROM; + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + //skip the first 4 bytes + ptr += 4; + + eepromformat = *(__OSContEepromFormat *)ptr; + + ret = CHNL_ERR(eepromformat); + + __osSiRelAccess(); + return ret; +} + +static void __osPackEepWriteData(u8 address, u8 *buffer) { + u8 *ptr = (u8 *)&__osEepPifRam.ramarray; + __OSContEepromFormat eepromformat; + int i; + + __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 < MAXCONTROLLERS; i++) { + *ptr++ = 0; + } + + *(__OSContEepromFormat *)(ptr) = eepromformat; + ptr += sizeof(__OSContEepromFormat); + ptr[0] = CONT_CMD_END; +} + + +s32 __osEepStatus(OSMesgQueue *mq, OSContStatus *data) { + s32 ret = 0; + int i; + u8 *ptr = (u8 *)__osEepPifRam.ramarray; + __OSContRequesFormat requestformat; + + for (i = 0; i < ARRLEN(__osEepPifRam.ramarray) + 1; i++) { + __osEepPifRam.ramarray[i] = 0; + } + + __osEepPifRam.pifstatus = CONT_CMD_EXE; + ptr = (u8 *)__osEepPifRam.ramarray; + + for (i = 0; i < MAXCONTROLLERS; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + + 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_END; + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + if (ret != 0) { + return ret; + } + + ptr = (u8 *)&__osEepPifRam; + + for (i = 0; i < MAXCONTROLLERS; 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; +} diff --git a/lib/ultralib/src/io/contpfs.c b/lib/ultralib/src/io/contpfs.c new file mode 100755 index 0000000..5121426 --- /dev/null +++ b/lib/ultralib/src/io/contpfs.c @@ -0,0 +1,297 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" + +__OSInode __osPfsInodeCache ALIGNED(8); +s32 __osPfsInodeCacheChannel = -1; +u8 __osPfsInodeCacheBank = 250; + +u16 __osSumcalc(u8 *ptr, int length) { + int i; + u32 sum = 0; + u8 *tmp = ptr; + + for (i = 0; i < length; i++) { + sum += *tmp++; + } + + return sum; +} + +s32 __osIdCheckSum(u16 *ptr, u16 *csum, u16 *icsum) { + u16 data = 0; + u32 j; + + *icsum = 0; + *csum = *icsum; + + for (j = 0; j < ((sizeof(__OSPackId) - sizeof(u32)) / sizeof(u8)); j += 2) { + data = *(u16 *)((u8 *)ptr + j); + *csum += data; + *icsum += ~data; + } + + return 0; +} + +s32 __osRepairPackId(OSPfs *pfs, __OSPackId *badid, __OSPackId *newid) { + s32 ret = 0; + u8 temp[BLOCKSIZE]; + u8 comp[BLOCKSIZE]; + u8 mask = 0; + int i; + int j = 0; + u16 index[4]; + + newid->repaired = -1; + newid->random = osGetCount(); + newid->serial_mid = badid->serial_mid; + newid->serial_low = badid->serial_low; + + SET_ACTIVEBANK_TO_ZERO; + + do { + ERRCK(__osPfsSelectBank(pfs, j)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, temp)); + + temp[0] = j | 0x80; + + for (i = 1; i < BLOCKSIZE; i++) { + temp[i] = ~temp[i]; + } + + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, 0, temp, FALSE)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, comp)); + + for (i = 0; i < BLOCKSIZE; i++) { + if (comp[i] != temp[i]) { + break; + } + } + + if (i != BLOCKSIZE) { + break; + } + + if (j > 0) { + ERRCK(__osPfsSelectBank(pfs, 0)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)temp)); + + if (temp[0] != 0x80) { + break; + } + } + + j++; + } while (j < PFS_MAX_BANKS); + + SET_ACTIVEBANK_TO_ZERO; + + 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] = PFS_ID_0AREA; + index[1] = PFS_ID_1AREA; + index[2] = PFS_ID_2AREA; + index[3] = PFS_ID_3AREA; + + for (i = 0; i < ARRLEN(index); i++) { + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, index[i], (u8*)newid, TRUE)); + } + + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, (u8*)temp)); + + for (i = 0; i < BLOCKSIZE; i++) { + if (temp[i] != ((u8 *)newid)[i]) { + return PFS_ERR_DEVICE; + } + } + return 0; +} + +s32 __osCheckPackId(OSPfs *pfs, __OSPackId *temp) { + u16 index[4]; + s32 ret = 0; + u16 sum; + u16 isum; + int i; + int j; + + SET_ACTIVEBANK_TO_ZERO; + index[0] = PFS_ID_0AREA; + index[1] = PFS_ID_1AREA; + index[2] = PFS_ID_2AREA; + index[3] = PFS_ID_3AREA; + 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[BLOCKSIZE]; + __OSPackId newid; + s32 ret; + __OSPackId *id; + + SET_ACTIVEBANK_TO_ZERO; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, (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) { + ERRCK(__osRepairPackId(pfs, id, &newid)); + id = &newid; + + if ((id->deviceid & 1) == 0) { + return PFS_ERR_DEVICE; + } + } + + bcopy(id, pfs->id, BLOCKSIZE); + pfs->version = id->version; + pfs->banks = id->banks; + pfs->inode_start_page = 1 + DEF_DIR_PAGES + (2 * pfs->banks); + pfs->dir_size = 16; + pfs->inode_table = PFS_ONE_PAGE; + pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE; + pfs->dir_table = pfs->minode_table + pfs->banks * PFS_ONE_PAGE; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label)); + return 0; +} + +s32 __osCheckId(OSPfs *pfs) { + u8 temp[BLOCKSIZE]; + s32 ret; + + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, 0); + + if (ret == PFS_ERR_NEW_PACK) { + ret = __osPfsSelectBank(pfs, 0); + } + + if (ret != 0) { + return ret; + } + } + + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, (u8*)temp); + + if (ret != 0) { + if (ret != PFS_ERR_NEW_PACK) { + return ret; + } else { + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, (u8*)temp)); + } + } + + if (bcmp(pfs->id, temp, BLOCKSIZE) != 0) { + 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; + + if (flag == PFS_READ && bank == __osPfsInodeCacheBank && (pfs->channel == __osPfsInodeCacheChannel)) { + bcopy(&__osPfsInodeCache, inode, sizeof(__OSInode)); + return 0; + } + + 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], (PFS_INODE_SIZE_PER_PAGE - offset) * 2); + } + + for (j = 0; j < PFS_ONE_PAGE; j++) { + addr = ((u8 *)inode->inode_page + j * BLOCKSIZE); + + if (flag == PFS_WRITE) { + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * PFS_ONE_PAGE + j, addr, FALSE); + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + 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], (PFS_INODE_SIZE_PER_PAGE - offset) * 2); + if (sum != inode->inode_page[0].inode_t.page) { + for (j = 0; j < PFS_ONE_PAGE; j++) { + addr = ((u8 *)inode->inode_page + j * BLOCKSIZE); + ret = __osContRamRead(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + j, addr); + } + + sum = __osSumcalc((u8*)&inode->inode_page[offset], (PFS_INODE_SIZE_PER_PAGE - offset) * 2); + + 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 * BLOCKSIZE); + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * PFS_ONE_PAGE + j, addr, FALSE); + } + } + } + + __osPfsInodeCacheBank = bank; + bcopy(inode, &__osPfsInodeCache, sizeof(__OSInode)); + __osPfsInodeCacheChannel = pfs->channel; + + return 0; +} diff --git a/lib/ultralib/src/io/contquery.c b/lib/ultralib/src/io/contquery.c new file mode 100755 index 0000000..d042ecf --- /dev/null +++ b/lib/ultralib/src/io/contquery.c @@ -0,0 +1,25 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +s32 osContStartQuery(OSMesgQueue *mq) { + s32 ret = 0; + + __osSiGetAccess(); + + if (__osContLastCmd != CONT_CMD_REQUEST_STATUS) { + __osPackRequestData(CONT_CMD_REQUEST_STATUS); + ret = __osSiRawStartDma(OS_WRITE, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + } + + ret = __osSiRawStartDma(OS_READ, __osContPifRam.ramarray); + __osContLastCmd = CONT_CMD_REQUEST_STATUS; + __osSiRelAccess(); + return ret; +} + +void osContGetQuery(OSContStatus *data) { + u8 pattern; + __osContGetInitData(&pattern, data); +} diff --git a/lib/ultralib/src/io/contramread.c b/lib/ultralib/src/io/contramread.c new file mode 100644 index 0000000..0afa93a --- /dev/null +++ b/lib/ultralib/src/io/contramread.c @@ -0,0 +1,75 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "controller.h" +#include "siint.h" + +s32 __osPfsLastChannel = -1; + +#define READFORMAT(ptr) ((__OSContRamReadFormat*)(ptr)) + +s32 __osContRamRead(OSMesgQueue* mq, int channel, u16 address, u8* buffer) { + s32 ret; + s32 i; + u8* ptr; + s32 retry = 2; + + __osSiGetAccess(); + + do { + ptr = (u8*)&__osPfsPifRam; + + if (__osContLastCmd != CONT_CMD_READ_PAK || __osPfsLastChannel != channel) { + __osContLastCmd = CONT_CMD_READ_PAK; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + READFORMAT(ptr)->dummy = CONT_CMD_NOP; + READFORMAT(ptr)->txsize = CONT_CMD_READ_PAK_TX; + READFORMAT(ptr)->rxsize = CONT_CMD_READ_PAK_RX; + READFORMAT(ptr)->cmd = CONT_CMD_READ_PAK; + READFORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSContRamReadFormat)] = CONT_CMD_END; + } else { + ptr += channel; + } + + READFORMAT(ptr)->addrh = address >> 3; + READFORMAT(ptr)->addrl = (u8)(__osContAddressCrc(address) | (address << 5)); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = CHNL_ERR(*READFORMAT(ptr)); + + if (!ret) { + if (__osContDataCrc(&READFORMAT(ptr)->data) != READFORMAT(ptr)->datacrc) { + ret = __osPfsGetStatus(mq, channel); + + if (ret) { + break; + } + + ret = PFS_ERR_CONTRFAIL; + } else { + bcopy(&READFORMAT(ptr)->data, buffer, BLOCKSIZE); + } + } else { + ret = PFS_ERR_NOPACK; + } + if (ret != PFS_ERR_CONTRFAIL) { + break; + } + } while (0 <= retry--); + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/io/contramwrite.c b/lib/ultralib/src/io/contramwrite.c new file mode 100644 index 0000000..1478480 --- /dev/null +++ b/lib/ultralib/src/io/contramwrite.c @@ -0,0 +1,77 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "controller.h" +#include "siint.h" + +extern s32 __osPfsLastChannel; + +#define READFORMAT(ptr) ((__OSContRamReadFormat*)(ptr)) + +s32 __osContRamWrite(OSMesgQueue* mq, int channel, u16 address, u8* buffer, int force) { + s32 ret = 0; + s32 i; + u8* ptr; + s32 retry = 2; + u8 crc; + + if ((force != TRUE) && (address < PFS_LABEL_AREA) && (address != 0)) { + return 0; + } + + __osSiGetAccess(); + + do { + ptr = __osPfsPifRam.ramarray; + + if (__osContLastCmd != CONT_CMD_WRITE_PAK || __osPfsLastChannel != channel) { + __osContLastCmd = CONT_CMD_WRITE_PAK; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + READFORMAT(ptr)->dummy = CONT_CMD_NOP; + READFORMAT(ptr)->txsize = CONT_CMD_WRITE_PAK_TX; + READFORMAT(ptr)->rxsize = CONT_CMD_WRITE_PAK_RX; + READFORMAT(ptr)->cmd = CONT_CMD_WRITE_PAK; + READFORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSContRamReadFormat)] = CONT_CMD_END; + } else { + ptr += channel; + } + + READFORMAT(ptr)->addrh = address >> 3; + READFORMAT(ptr)->addrl = ((address << 5) | __osContAddressCrc(address)); + + bcopy(buffer, READFORMAT(ptr)->data, BLOCKSIZE); + + ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + crc = __osContDataCrc(buffer); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = CHNL_ERR(*READFORMAT(ptr)); + + if (!ret) { + if (crc != READFORMAT(ptr)->datacrc) { + if ((ret = __osPfsGetStatus(mq, channel))) { + break; + } else { + ret = PFS_ERR_CONTRFAIL; + } + } + } else { + ret = PFS_ERR_NOPACK; + } + } while ((ret == PFS_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +}
\ No newline at end of file diff --git a/lib/ultralib/src/io/contreaddata.c b/lib/ultralib/src/io/contreaddata.c new file mode 100644 index 0000000..60b9493 --- /dev/null +++ b/lib/ultralib/src/io/contreaddata.c @@ -0,0 +1,68 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +static void __osPackReadData(void); + +s32 osContStartReadData(OSMesgQueue* mq) { + s32 ret = 0; + + __osSiGetAccess(); + + if (__osContLastCmd != CONT_CMD_READ_BUTTON) { + __osPackReadData(); + ret = __osSiRawStartDma(OS_WRITE, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + } + + ret = __osSiRawStartDma(OS_READ, __osContPifRam.ramarray); + __osContLastCmd = CONT_CMD_READ_BUTTON; + __osSiRelAccess(); + + return ret; +} + +void osContGetReadData(OSContPad* data) { + u8* ptr = __osContPifRam.ramarray; + __OSContReadFormat readformat; + int i; + + for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(__OSContReadFormat), data++) { + readformat = *(__OSContReadFormat*)ptr; + data->errno = CHNL_ERR(readformat); + + if (data->errno != 0) { + continue; + } + + data->button = readformat.button; + data->stick_x = readformat.stick_x; + data->stick_y = readformat.stick_y; + } +} + +static void __osPackReadData(void) { + u8* ptr = __osContPifRam.ramarray; + __OSContReadFormat readformat; + int i; + + for (i = 0; i < ARRLEN(__osContPifRam.ramarray); 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 = 0xFFFF; + readformat.stick_x = -1; + readformat.stick_y = -1; + + for (i = 0; i < __osMaxControllers; i++) { + *(__OSContReadFormat*)ptr = readformat; + ptr += sizeof(__OSContReadFormat); + } + + *ptr = CONT_CMD_END; +} diff --git a/lib/ultralib/src/io/contreset.c b/lib/ultralib/src/io/contreset.c new file mode 100644 index 0000000..ab30a47 --- /dev/null +++ b/lib/ultralib/src/io/contreset.c @@ -0,0 +1,51 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +void __osPackResetData(void); + +s32 osContReset(OSMesgQueue *mq, OSContStatus *data) { + u8 pattern; + s32 ret; + + __osSiGetAccess(); + + if (__osContLastCmd != CONT_CMD_RESET) { + __osPackResetData(); + + ret = __osSiRawStartDma(OS_WRITE, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osPackRequestData(CONT_CMD_RESET); + + ret = __osSiRawStartDma(OS_WRITE, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osContLastCmd = CONT_CMD_RESET; + } + + ret = __osSiRawStartDma(OS_READ, __osContPifRam.ramarray); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + __osContGetInitData(&pattern, data); + __osSiRelAccess(); + + return ret; +} + +void __osPackResetData(void) { + u8 *ptr; + int i; + + __osContPifRam.pifstatus = CONT_CMD_EXE; + ptr = __osContPifRam.ramarray; + + for (i = 0; i < MAXCONTROLLERS; i++) { + *ptr++ = CONT_CMD_CHANNEL_RESET; + } + + *ptr = CONT_CMD_END; +} diff --git a/lib/ultralib/src/io/controller.c b/lib/ultralib/src/io/controller.c new file mode 100644 index 0000000..db9b769 --- /dev/null +++ b/lib/ultralib/src/io/controller.c @@ -0,0 +1,99 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" + +s32 __osContinitialized = 0; + +OSPifRam __osContPifRam ALIGNED(16); +u8 __osContLastCmd; +u8 __osMaxControllers; + +OSTimer __osEepromTimer; +OSMesgQueue __osEepromTimerQ ALIGNED(8); +OSMesg __osEepromTimerMsg; + +s32 osContInit(OSMesgQueue* mq, u8* bitpattern, OSContStatus* data) { + OSMesg dummy; + s32 ret = 0; + OSTime t; + OSTimer mytimer; + OSMesgQueue timerMesgQueue; + + if (__osContinitialized != 0) { + return 0; + } + + __osContinitialized = 1; + + t = osGetTime(); + if (t < OS_USEC_TO_CYCLES(500000)) { + osCreateMesgQueue(&timerMesgQueue, &dummy, 1); + osSetTimer(&mytimer, OS_USEC_TO_CYCLES(500000) - t, 0, &timerMesgQueue, &dummy); + osRecvMesg(&timerMesgQueue, &dummy, OS_MESG_BLOCK); + } + + __osMaxControllers = 4; + + __osPackRequestData(CONT_CMD_REQUEST_STATUS); + + ret = __osSiRawStartDma(OS_WRITE, __osContPifRam.ramarray); + osRecvMesg(mq, &dummy, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, __osContPifRam.ramarray); + 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 requestHeader; + s32 i; + u8 bits; + + bits = 0; + ptr = __osContPifRam.ramarray; + for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(requestHeader), data++) { + requestHeader = *(__OSContRequesFormat*)ptr; + data->errno = CHNL_ERR(requestHeader); + if (data->errno == 0) { + data->type = requestHeader.typel << 8 | requestHeader.typeh; + data->status = requestHeader.status; + + bits |= 1 << i; + } + } + *pattern = bits; +} + +void __osPackRequestData(u8 cmd) { + u8* ptr; + __OSContRequesFormat requestHeader; + s32 i; + + for (i = 0; i < ARRLEN(__osContPifRam.ramarray); i++) { + __osContPifRam.ramarray[i] = 0; + } + + __osContPifRam.pifstatus = CONT_CMD_EXE; + ptr = __osContPifRam.ramarray; + requestHeader.dummy = CONT_CMD_NOP; + requestHeader.txsize = CONT_CMD_RESET_TX; + requestHeader.rxsize = CONT_CMD_RESET_RX; + requestHeader.cmd = cmd; + requestHeader.typeh = CONT_CMD_NOP; + requestHeader.typel = CONT_CMD_NOP; + requestHeader.status = CONT_CMD_NOP; + requestHeader.dummy1 = CONT_CMD_NOP; + + for (i = 0; i < __osMaxControllers; i++) { + *(__OSContRequesFormat*)ptr = requestHeader; + ptr += sizeof(requestHeader); + } + *ptr = CONT_CMD_END; +} diff --git a/lib/ultralib/src/io/controller.h b/lib/ultralib/src/io/controller.h new file mode 100755 index 0000000..efce970 --- /dev/null +++ b/lib/ultralib/src/io/controller.h @@ -0,0 +1,257 @@ +#ifndef _CONTROLLER_H +#define _CONTROLLER_H + +#include "PR/os_internal.h" +#include "PR/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 */ u8 addrh; + /* 0x5 */ u8 addrl; + /* 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; + +// Joybus commands +//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_PAK 2 +#define CONT_CMD_WRITE_PAK 3 +#define CONT_CMD_READ_EEPROM 4 +#define CONT_CMD_WRITE_EEPROM 5 +#define CONT_CMD_READ36_VOICE 9 +#define CONT_CMD_WRITE20_VOICE 10 +#define CONT_CMD_READ2_VOICE 11 +#define CONT_CMD_WRITE4_VOICE 12 +#define CONT_CMD_SWRITE_VOICE 13 +#define CONT_CMD_CHANNEL_RESET 0xFD +#define CONT_CMD_RESET 0xFF + +// Bytes transmitted for each joybus command +#define CONT_CMD_REQUEST_STATUS_TX 1 +#define CONT_CMD_READ_BUTTON_TX 1 +#define CONT_CMD_READ_PAK_TX 3 +#define CONT_CMD_WRITE_PAK_TX 35 +#define CONT_CMD_READ_EEPROM_TX 2 +#define CONT_CMD_WRITE_EEPROM_TX 10 +#define CONT_CMD_READ36_VOICE_TX 3 +#define CONT_CMD_WRITE20_VOICE_TX 23 +#define CONT_CMD_READ2_VOICE_TX 3 +#define CONT_CMD_WRITE4_VOICE_TX 7 +#define CONT_CMD_SWRITE_VOICE_TX 3 +#define CONT_CMD_RESET_TX 1 + +// Bytes received for each joybus command +#define CONT_CMD_REQUEST_STATUS_RX 3 +#define CONT_CMD_READ_BUTTON_RX 4 +#define CONT_CMD_READ_PAK_RX 33 +#define CONT_CMD_WRITE_PAK_RX 1 +#define CONT_CMD_READ_EEPROM_RX 8 +#define CONT_CMD_WRITE_EEPROM_RX 1 +#define CONT_CMD_READ36_VOICE_RX 37 +#define CONT_CMD_WRITE20_VOICE_RX 1 +#define CONT_CMD_READ2_VOICE_RX 3 +#define CONT_CMD_WRITE4_VOICE_RX 1 +#define CONT_CMD_SWRITE_VOICE_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 + +// Controller accessory addresses +// https://github.com/joeldipops/TransferBoy/blob/master/docs/TransferPakReference.md + +// Accesory detection +#define CONT_ADDR_DETECT 0x8000 +// Rumble +#define CONT_ADDR_RUMBLE 0xC000 +// Controller Pak +// Transfer Pak +#define CONT_ADDR_GB_POWER 0x8000 // Same as the detection address, but semantically different +#define CONT_ADDR_GB_BANK 0xA000 +#define CONT_ADDR_GB_STATUS 0xB000 + +// Addresses sent to controller accessories are in blocks, not bytes +#define CONT_BLOCKS(x) ((x) / BLOCKSIZE) + +// Block addresses of the above +#define CONT_BLOCK_DETECT CONT_BLOCKS(CONT_ADDR_DETECT) +#define CONT_BLOCK_RUMBLE CONT_BLOCKS(CONT_ADDR_RUMBLE) +#define CONT_BLOCK_GB_POWER CONT_BLOCKS(CONT_ADDR_GB_POWER) +#define CONT_BLOCK_GB_BANK CONT_BLOCKS(CONT_ADDR_GB_BANK) +#define CONT_BLOCK_GB_STATUS CONT_BLOCKS(CONT_ADDR_GB_STATUS) + + +// Transfer pak + +#define GB_POWER_ON 0x84 +#define GB_POWER_OFF 0xFE + + +typedef struct +{ + /* 0x0 */ __OSInode inode; + /* 0x100 */ u8 bank; + /* 0x101 */ u8 map[PFS_INODE_DIST_MAP]; +} __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, u8 bank); +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, u8 bank, __OSInodeUnit *last_page); +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) \ + { \ + ERRCK(__osPfsSelectBank(pfs, 0)) \ + } + +#define PFS_CHECK_ID \ + if (__osCheckId(pfs) == PFS_ERR_NEW_PACK) \ + return PFS_ERR_NEW_PACK; + +#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; + +#endif diff --git a/lib/ultralib/src/io/controller_gbpak.h b/lib/ultralib/src/io/controller_gbpak.h new file mode 100644 index 0000000..db98bd4 --- /dev/null +++ b/lib/ultralib/src/io/controller_gbpak.h @@ -0,0 +1,8 @@ +#ifndef _CONTROLLER_GBPAK_H +#define _CONTROLLER_GBPAK_H + +extern OSTimer __osGbpakTimer; +extern OSMesg __osGbpakTimerMsg; +extern OSMesgQueue __osGbpakTimerQ; + +#endif diff --git a/lib/ultralib/src/io/controller_voice.h b/lib/ultralib/src/io/controller_voice.h new file mode 100644 index 0000000..7223d06 --- /dev/null +++ b/lib/ultralib/src/io/controller_voice.h @@ -0,0 +1,59 @@ +#ifndef CONTROLLER_VOICE_H +#define CONTROLLER_VOICE_H + +#include <PR/ultratypes.h> + +typedef struct { + /* 0x0 */ u8 dummy; + /* 0x1 */ u8 txsize; + /* 0x2 */ u8 rxsize; + /* 0x3 */ u8 cmd; + /* 0x4 */ u8 addrh; + /* 0x5 */ u8 addrl; + /* 0x6 */ u8 data[2]; + /* 0x8 */ u8 datacrc; +} __OSVoiceRead2Format; + +typedef struct { + /* 0x0 */ u8 dummy; + /* 0x1 */ u8 txsize; + /* 0x2 */ u8 rxsize; + /* 0x3 */ u8 cmd; + /* 0x4 */ u8 addrh; + /* 0x5 */ u8 addrl; + /* 0x6 */ u8 data[36]; + /* 0x2A */ u8 datacrc; +} __OSVoiceRead36Format; + +typedef struct { + /* 0x0 */ u8 dummy; + /* 0x1 */ u8 txsize; + /* 0x2 */ u8 rxsize; + /* 0x3 */ u8 cmd; + /* 0x4 */ u8 addrh; + /* 0x5 */ u8 addrl; + /* 0x6 */ u8 data[4]; + /* 0xA */ u8 datacrc; +} __OSVoiceWrite4Format; + +typedef struct { + /* 0x0 */ u8 dummy; + /* 0x1 */ u8 txsize; + /* 0x2 */ u8 rxsize; + /* 0x3 */ u8 cmd; + /* 0x4 */ u8 addrh; + /* 0x5 */ u8 addrl; + /* 0x6 */ u8 data[20]; + /* 0x1A */ u8 datacrc; +} __OSVoiceWrite20Format; + +typedef struct { + /* 0x0 */ u8 txsize; + /* 0x1 */ u8 rxsize; + /* 0x2 */ u8 cmd; + /* 0x3 */ u8 data; + /* 0x4 */ u8 scrc; + /* 0x5 */ u8 datacrc; +} __OSVoiceSWriteFormat; + +#endif // CONTROLLER_VOICE_H diff --git a/lib/ultralib/src/io/contsetch.c b/lib/ultralib/src/io/contsetch.c new file mode 100644 index 0000000..eff63a6 --- /dev/null +++ b/lib/ultralib/src/io/contsetch.c @@ -0,0 +1,19 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +s32 osContSetCh(u8 ch) { + s32 ret = 0; + + __osSiGetAccess(); + + if (ch > MAXCONTROLLERS) { + __osMaxControllers = MAXCONTROLLERS; + } else { + __osMaxControllers = ch; + } + + __osContLastCmd = CONT_CMD_END; + __osSiRelAccess(); + return ret; +}
\ No newline at end of file diff --git a/lib/ultralib/src/io/crc.c b/lib/ultralib/src/io/crc.c new file mode 100644 index 0000000..e266152 --- /dev/null +++ b/lib/ultralib/src/io/crc.c @@ -0,0 +1,64 @@ +#include "PR/os_internal.h" + +u8 __osContAddressCrc(u16 addr) { + u32 temp = 0; + u32 i; + + for (i = 0x400; i != 0;) { + temp <<= 1; + + if (addr & i) { + if (temp & 0x20) { + temp ^= 0x14; + } else { + ++temp; + } + } else if (temp & 0x20) { + temp ^= 0x15; + } + + i >>= 1; + } + + for (i = 5; i != 0; --i) { + temp <<= 1; + if (temp & 0x20) { + temp ^= 0x15; + } + } + + return temp & 0x1F; +} + +u8 __osContDataCrc(u8 *data) { + u32 temp = 0; + u32 i; + u32 j; + + for (i = 0x20; i; --i) { + for (j = 0x80; j; j >>= 1) { + temp <<= 1; + + if ((*data & j) != 0) { + if ((temp & 0x100) != 0) { + temp ^= 0x84; + } else { + ++temp; + } + } else if (temp & 0x100) { + temp ^= 0x85; + } + } + + data++; + } + do { + temp <<= 1; + + if (temp & 0x100) { + temp ^= 0x85; + } + } while (++i < 8U); + + return temp; +} diff --git a/lib/ultralib/src/io/devmgr.c b/lib/ultralib/src/io/devmgr.c new file mode 100644 index 0000000..2d22774 --- /dev/null +++ b/lib/ultralib/src/io/devmgr.c @@ -0,0 +1,110 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "piint.h" + +void __osDevMgrMain(void *args) +{ + OSIoMesg *mb = NULL; + OSMesg em; + OSMesg dummy; + s32 ret = 0; + OSDevMgr *dm = (OSDevMgr *)args; + s32 messageSend = 0; + + 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)); + +readblock1: + 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); + __osEPiRawWriteIo(mb->piHandle, LEO_BM_CTL, info->bmCtlShadow); + __osEPiRawReadIo(mb->piHandle, LEO_STATUS, &stat); + + if (stat & LEO_STATUS_MECHANIC_INTERRUPT) { + __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 && mb->piHandle->transferInfo.block[0].errStatus == LEO_ERROR_GOOD) { + messageSend = 0; + goto readblock1; + } + + 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); + } + } + } +} diff --git a/lib/ultralib/src/io/dp.c b/lib/ultralib/src/io/dp.c new file mode 100755 index 0000000..e4d0254 --- /dev/null +++ b/lib/ultralib/src/io/dp.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +int __osDpDeviceBusy(void) { + register u32 stat = IO_READ(DPC_STATUS_REG); + + if (stat & DPC_STATUS_DMA_BUSY) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/ultralib/src/io/dpctr.c b/lib/ultralib/src/io/dpctr.c new file mode 100755 index 0000000..0c2164b --- /dev/null +++ b/lib/ultralib/src/io/dpctr.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +void osDpGetCounters(u32 *array) { + *array++ = IO_READ(DPC_CLOCK_REG); + *array++ = IO_READ(DPC_BUFBUSY_REG); + *array++ = IO_READ(DPC_PIPEBUSY_REG); + *array++ = IO_READ(DPC_TMEM_REG); +} diff --git a/lib/ultralib/src/io/dpgetstat.c b/lib/ultralib/src/io/dpgetstat.c new file mode 100755 index 0000000..af3ccee --- /dev/null +++ b/lib/ultralib/src/io/dpgetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 osDpGetStatus() { + return IO_READ(DPC_STATUS_REG); +} diff --git a/lib/ultralib/src/io/dpsetnextbuf.c b/lib/ultralib/src/io/dpsetnextbuf.c new file mode 100755 index 0000000..fa9a0d4 --- /dev/null +++ b/lib/ultralib/src/io/dpsetnextbuf.c @@ -0,0 +1,24 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osDpSetNextBuffer(void *bufPtr, u64 size) { + register u32 stat; + + if (__osDpDeviceBusy()) { + return -1; + } + + IO_WRITE(DPC_STATUS_REG, DPC_CLR_XBUS_DMEM_DMA); + + do { + stat = IO_READ(DPC_STATUS_REG); + } while (stat & DPC_STATUS_XBUS_DMEM_DMA); + + IO_WRITE(DPC_START_REG, osVirtualToPhysical(bufPtr)); + IO_WRITE(DPC_END_REG, osVirtualToPhysical(bufPtr) + size); + return 0; +} diff --git a/lib/ultralib/src/io/dpsetstat.c b/lib/ultralib/src/io/dpsetstat.c new file mode 100755 index 0000000..5b53867 --- /dev/null +++ b/lib/ultralib/src/io/dpsetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osDpSetStatus(u32 data) { + IO_WRITE(DPC_STATUS_REG, data); +} diff --git a/lib/ultralib/src/io/epidma.c b/lib/ultralib/src/io/epidma.c new file mode 100644 index 0000000..d122791 --- /dev/null +++ b/lib/ultralib/src/io/epidma.c @@ -0,0 +1,24 @@ +#include "piint.h" + +s32 osEPiStartDma(OSPiHandle* pihandle, OSIoMesg* mb, s32 direction) { + s32 ret; + + if (!__osPiDevMgr.active) { + return -1; + } + mb->piHandle = pihandle; + + if (direction == OS_READ) { + mb->hdr.type = OS_MESG_TYPE_EDMAREAD; + } else { + mb->hdr.type = OS_MESG_TYPE_EDMAWRITE; + } + + if (mb->hdr.pri == OS_MESG_PRI_HIGH) { + ret = osJamMesg(osPiGetCmdQueue(), (OSMesg)mb, OS_MESG_NOBLOCK); + } else { + ret = osSendMesg(osPiGetCmdQueue(), (OSMesg)mb, OS_MESG_NOBLOCK); + } + + return ret; +} diff --git a/lib/ultralib/src/io/epigettype.c b/lib/ultralib/src/io/epigettype.c new file mode 100644 index 0000000..ef749ea --- /dev/null +++ b/lib/ultralib/src/io/epigettype.c @@ -0,0 +1,8 @@ +#include "piint.h" + +s32 osEPiGetDeviceType(OSPiHandle *pihandle, OSPiInfo *info) +{ + info->type = pihandle->type; + info->address = pihandle->baseAddress; + return 0; +} diff --git a/lib/ultralib/src/io/epilinkhandle.c b/lib/ultralib/src/io/epilinkhandle.c new file mode 100644 index 0000000..8785bdb --- /dev/null +++ b/lib/ultralib/src/io/epilinkhandle.c @@ -0,0 +1,12 @@ +#include "piint.h" + +s32 osEPiLinkHandle(OSPiHandle *EPiHandle) +{ + register s32 saveMask = __osDisableInt(); + + EPiHandle->next = __osPiTable; + __osPiTable = EPiHandle; + + __osRestoreInt(saveMask); + return 0; +} diff --git a/lib/ultralib/src/io/epirawdma.c b/lib/ultralib/src/io/epirawdma.c new file mode 100644 index 0000000..63ad6cf --- /dev/null +++ b/lib/ultralib/src/io/epirawdma.c @@ -0,0 +1,27 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +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; +} diff --git a/lib/ultralib/src/io/epirawread.c b/lib/ultralib/src/io/epirawread.c new file mode 100644 index 0000000..7871f56 --- /dev/null +++ b/lib/ultralib/src/io/epirawread.c @@ -0,0 +1,14 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osEPiRawReadIo(OSPiHandle* pihandle, u32 devAddr, u32* data) { + u32 stat; + u32 domain; + + EPI_SYNC(pihandle, stat, domain); + *data = IO_READ(pihandle->baseAddress | devAddr); + + return 0; +} diff --git a/lib/ultralib/src/io/epirawwrite.c b/lib/ultralib/src/io/epirawwrite.c new file mode 100644 index 0000000..5cc1752 --- /dev/null +++ b/lib/ultralib/src/io/epirawwrite.c @@ -0,0 +1,14 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osEPiRawWriteIo(OSPiHandle* pihandle, u32 devAddr, u32 data) { + u32 stat; + u32 domain; + + EPI_SYNC(pihandle, stat, domain); + IO_WRITE(pihandle->baseAddress | devAddr, data); + + return 0; +} diff --git a/lib/ultralib/src/io/epiread.c b/lib/ultralib/src/io/epiread.c new file mode 100644 index 0000000..3918c5f --- /dev/null +++ b/lib/ultralib/src/io/epiread.c @@ -0,0 +1,13 @@ +#include "piint.h" + +s32 __osEPiRawReadIo(OSPiHandle*, u32, u32*); + +s32 osEPiReadIo(OSPiHandle* pihandle, u32 devAddr, u32* data) { + register s32 ret; + + __osPiGetAccess(); + ret = __osEPiRawReadIo(pihandle, devAddr, data); + __osPiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/io/epiwrite.c b/lib/ultralib/src/io/epiwrite.c new file mode 100644 index 0000000..1a4c462 --- /dev/null +++ b/lib/ultralib/src/io/epiwrite.c @@ -0,0 +1,13 @@ +#include "piint.h" + +s32 __osEPiRawWriteIo(OSPiHandle*, u32, u32); + +s32 osEPiWriteIo(OSPiHandle* pihandle, u32 devAddr, u32 data) { + register s32 ret; + + __osPiGetAccess(); + ret = __osEPiRawWriteIo(pihandle, devAddr, data); + __osPiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakcheckconnector.c b/lib/ultralib/src/io/gbpakcheckconnector.c new file mode 100644 index 0000000..7fbef18 --- /dev/null +++ b/lib/ultralib/src/io/gbpakcheckconnector.c @@ -0,0 +1,131 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" + +s32 osGbpakCheckConnector(OSPfs* pfs, u8* status) { + s32 ret; + s32 bufn = 1; + s32 oldbufn = 0; + u16 address = 0; + u16 oldaddr = 0; + u16 daddr = 0; + u16 num; + u8 buf[3][4][BLOCKSIZE]; + u8 buf_status[3][4]; + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = osGbpakGetStatus(pfs, status); + } + + if (ret == PFS_ERR_NEW_GBCART) { + return PFS_ERR_CONTRFAIL; + } else if (ret == 0) { + if (!(*status & OS_GBPAK_POWER)) { + ERRCK(osGbpakPower(pfs, OS_GBPAK_POWER_ON)); + } + + bzero(buf_status, sizeof(buf_status)); + + for (address = 0x80; address <= 0x4000; address <<= 1) { + num = 0; + daddr = 0; + + do { + ERRCK(osGbpakReadWrite(pfs, OS_READ, address + daddr, buf[bufn][num], BLOCKSIZE)); + buf_status[bufn][num] = 1; + + if (buf_status[oldbufn][num] == 0) { + ret = osGbpakReadWrite(pfs, OS_READ, oldaddr + daddr, buf[oldbufn][num], BLOCKSIZE); + + if (ret != 0) { + return ret; + } else { + buf_status[oldbufn][num] = 1; + } + } + + if (bcmp(buf[bufn][num], buf[oldbufn][num], BLOCKSIZE) != 0) { + num = 0; + break; + } + + daddr += BLOCKSIZE; + } while (num++ < ARRLEN(buf[0]) - 1); + + if (num != 0) { + return PFS_ERR_CONTRFAIL; + } + + if (oldbufn != 0) { + num = 0; + daddr = 0; + + do { + if (buf_status[bufn][num] == 0) { + ERRCK(osGbpakReadWrite(pfs, OS_READ, address + daddr, buf[bufn][num], BLOCKSIZE)); + buf_status[bufn][num] = 1; + } + + if (buf_status[0][num] == 0) { + ret = osGbpakReadWrite(pfs, OS_READ, daddr, buf[0][num], BLOCKSIZE); + if (ret != 0) { + return ret; + } else { + buf_status[0][num] = 1; + } + } + + if (bcmp(buf[bufn][num], buf[0][num], BLOCKSIZE)) { + num = 0; + break; + } + + daddr += BLOCKSIZE; + } while (num++ < ARRLEN(buf_status[0]) - 1); + } + + if (num != 0) { + return PFS_ERR_CONTRFAIL; + } + + if (oldbufn != 0) { + bzero(buf_status[oldbufn], ARRLEN(buf_status[oldbufn])); + } + + oldaddr = address; + oldbufn = bufn; + bufn ^= 3; + } + + if ((pfs->dir_size >= 2) || (pfs->version == 2)) { + num = 0; + daddr = 0; + + do { + ERRCK(osGbpakReadWrite(pfs, OS_READ, daddr + 0xA000, buf[bufn][num], BLOCKSIZE)); + ERRCK(osGbpakReadWrite(pfs, OS_READ, daddr + 0x2000, buf[oldbufn][num], BLOCKSIZE)); + + if (bcmp(buf[bufn][num], buf[oldbufn][num], BLOCKSIZE)) { + num = 0; + break; + } + + daddr += BLOCKSIZE; + } while (num++ < ARRLEN(buf[0]) - 1); + + if (num != 0) { + return PFS_ERR_CONTRFAIL; + } + } + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = PFS_ERR_CONTRFAIL; + } + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakgetbank.c b/lib/ultralib/src/io/gbpakgetbank.c new file mode 100644 index 0000000..622e707 --- /dev/null +++ b/lib/ultralib/src/io/gbpakgetbank.c @@ -0,0 +1,28 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 __osGbpakGetBank(OSPfs* pfs, u8* bank) { + s32 ret; + u32 temp[BLOCKSIZE / sizeof(u32)]; + + ret = __osContRamRead(pfs->queue, pfs->channel, CONT_BLOCK_GB_BANK, (u8*)temp); + + if (ret == PFS_ERR_NEW_PACK) { + ret = osGbpakInit(pfs->queue, pfs, pfs->channel); + + if (ret == 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, CONT_BLOCK_GB_BANK, (u8*)temp); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + } + } + + if (ret == 0) { + *bank = ((u8*)temp)[0]; + pfs->banks = *bank; + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakgetstatus.c b/lib/ultralib/src/io/gbpakgetstatus.c new file mode 100644 index 0000000..d17d15c --- /dev/null +++ b/lib/ultralib/src/io/gbpakgetstatus.c @@ -0,0 +1,39 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osGbpakGetStatus(OSPfs* pfs, u8* status) { + s32 ret; + s32 i; + u32 temp[BLOCKSIZE / sizeof(u32)]; + + ret = __osContRamRead(pfs->queue, pfs->channel, CONT_BLOCK_GB_POWER, (u8*)temp); + + if ((ret == PFS_ERR_NEW_PACK) || (((u8*)temp)[BLOCKSIZE - 1] != GB_POWER_ON)) { + ERRCK(osGbpakInit(pfs->queue, pfs, pfs->channel)); + } + + ret = __osContRamRead(pfs->queue, pfs->channel, CONT_BLOCK_GB_STATUS, (u8*)temp); + + if (ret == 0) { + ERRCK(__osPfsGetStatus(pfs->queue, pfs->channel)); + + *status = ((u8*)temp)[0]; + + for (i = 1; i < BLOCKSIZE; i++) { + *status |= ((u8*)temp)[i]; + } + + *status &= (OS_GBPAK_GBCART_PULL | OS_GBPAK_RSTB_DETECTION); + *status |= ((u8*)temp)[BLOCKSIZE - 1]; + + if (!(*status & OS_GBPAK_GBCART_ON)) { + ret = PFS_ERR_NO_GBCART; + } else if (*status & OS_GBPAK_GBCART_PULL) { + ret = PFS_ERR_NEW_GBCART; + } + } else if (ret == 2) { + ret = PFS_ERR_CONTRFAIL; + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakinit.c b/lib/ultralib/src/io/gbpakinit.c new file mode 100644 index 0000000..604bafa --- /dev/null +++ b/lib/ultralib/src/io/gbpakinit.c @@ -0,0 +1,90 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" +#include "controller_gbpak.h" + +OSTimer __osGbpakTimer; +OSMesg __osGbpakTimerMsg; +OSMesgQueue __osGbpakTimerQ ALIGNED(8); + +s32 osGbpakInit(OSMesgQueue* mq, OSPfs* pfs, int channel) { + int i; + s32 ret; + u8 temp[BLOCKSIZE]; + + pfs->status = 0; + + // Turn off the transfer pak + for (i = 0; i < BLOCKSIZE; i++) { + temp[i] = GB_POWER_OFF; + } + + ret = __osContRamWrite(mq, channel, CONT_BLOCK_GB_POWER, temp, FALSE); + if (ret == PFS_ERR_NEW_PACK) { + ret = __osContRamWrite(mq, channel, CONT_BLOCK_GB_POWER, temp, FALSE); + } + + if (ret != 0) { + return ret; + } + + ret = __osContRamRead(mq, channel, CONT_BLOCK_GB_POWER, temp); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } else { + // Check if the power is still off as set earlier + if (temp[BLOCKSIZE - 1] == GB_POWER_OFF) { + return PFS_ERR_DEVICE; + } + } + + // Turn on the transfer pak + for (i = 0; i < BLOCKSIZE; i++) { + temp[i] = GB_POWER_ON; + } + + ret = __osContRamWrite(mq, channel, CONT_BLOCK_GB_POWER, temp, FALSE); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + ret = __osContRamRead(mq, channel, CONT_BLOCK_GB_POWER, temp); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } else { + // Check if the power is still on as set earlier + if (temp[BLOCKSIZE - 1] != GB_POWER_ON) { + return PFS_ERR_DEVICE; + } + } + + ERRCK(__osPfsGetStatus(mq, channel)); + + osCreateMesgQueue(&__osGbpakTimerQ, &__osGbpakTimerMsg, 1); + osSetTimer(&__osGbpakTimer, 9000000, 0, &__osGbpakTimerQ, &__osGbpakTimerMsg); + osRecvMesg(&__osGbpakTimerQ, NULL, OS_MESG_BLOCK); + pfs->queue = mq; + pfs->status = PFS_GBPAK_INITIALIZED; + pfs->channel = channel; + pfs->activebank = 0x84; + pfs->banks = 0xFF; + pfs->version = 0xFF; + pfs->dir_size = 0xFF; + + return 0; +} diff --git a/lib/ultralib/src/io/gbpakpower.c b/lib/ultralib/src/io/gbpakpower.c new file mode 100644 index 0000000..c0b78cb --- /dev/null +++ b/lib/ultralib/src/io/gbpakpower.c @@ -0,0 +1,34 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "controller_gbpak.h" + +s32 osGbpakPower(OSPfs* pfs, s32 flag) { + s32 i; + s32 ret; + u8 temp[BLOCKSIZE]; + + for (i = 0; i < BLOCKSIZE; i++) { + temp[i] = (u8) flag; + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, CONT_BLOCK_GB_STATUS, temp, 0); + + if (ret == PFS_ERR_NEW_PACK) { + ret = osGbpakInit(pfs->queue, pfs, pfs->channel); + + if (ret == 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, CONT_BLOCK_GB_STATUS, temp, 0); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + } + } + + if (flag != OS_GBPAK_POWER_OFF) { + osSetTimer(&__osGbpakTimer, OS_USEC_TO_CYCLES(120000), 0, &__osGbpakTimerQ, &__osGbpakTimerMsg); + osRecvMesg(&__osGbpakTimerQ, NULL, OS_MESG_BLOCK); + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakreadid.c b/lib/ultralib/src/io/gbpakreadid.c new file mode 100644 index 0000000..d0cf467 --- /dev/null +++ b/lib/ultralib/src/io/gbpakreadid.c @@ -0,0 +1,84 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" + +s32 osGbpakReadId(OSPfs* pfs, OSGbpakId* id, u8* status) { + s32 i; + s32 ret; + u8 isum; + u8 buf[96]; + u8 temp[32]; + static u8 nintendo[] = {0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E}; + static u8 mmc_type[] = {0x00, 0x01, 0x01, 0x01, 0xFF, 0x02, 0x02, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03}; + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = osGbpakGetStatus(pfs, status); + } + + if (ret == PFS_ERR_NEW_GBCART) { + return PFS_ERR_CONTRFAIL; + } else if (ret == 0) { + if (!(*status & OS_GBPAK_POWER)) { + ERRCK(osGbpakPower(pfs, OS_GBPAK_POWER_ON)); + } + + ERRCK(osGbpakReadWrite(pfs, OS_READ, 0x100U, buf, ARRLEN(buf))); + + ret = osGbpakGetStatus(pfs, status); + + if (ret == 0xD) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + if (!(*status & OS_GBPAK_RSTB_STATUS)) { + return PFS_ERR_CONTRFAIL; + } + + if (bcmp(nintendo, buf + 4, ARRLEN(nintendo))) { + for (i = 0; i < ARRLEN(temp); i++) { + temp[i] = 0; + } + + ERRCK(osGbpakReadWrite(pfs, OS_WRITE, 0x6000U, temp, ARRLEN(temp))); + ret = osGbpakReadWrite(pfs, OS_READ, 0x100U, buf, ARRLEN(buf)); + ERRCK(osGbpakReadWrite(pfs, OS_READ, 0x100U, buf, ARRLEN(buf))); + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + if (bcmp(nintendo, buf + 4, ARRLEN(nintendo))) { + return 4; + } + } + for (i = 0x34, isum = 0; i < 0x4E; i++) { + isum += buf[i]; + } + + if ((isum + 0x19) & 0xFF) { + return 4; + } + + bcopy(buf, id, 0x50); + + if (id->cart_type < 0x14) { + pfs->version = (int)mmc_type[id->cart_type]; + } + + pfs->dir_size = (int)id->ram_size; + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpakreadwrite.c b/lib/ultralib/src/io/gbpakreadwrite.c new file mode 100644 index 0000000..5fac5ce --- /dev/null +++ b/lib/ultralib/src/io/gbpakreadwrite.c @@ -0,0 +1,69 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osGbpakReadWrite(OSPfs* pfs, u16 flag, u16 address, u8* buffer, u16 size) { + s32 i; + s32 ret; + u8 bank; + + bank = (u8) (address >> 0xE); + + if (bank != pfs->banks) { + ret = __osGbpakSetBank(pfs, bank); + + if (ret != 0) { + return ret; + } + } + + if (size == 0) { + return 0; + } + + size = (u16)(size >> 5); + address = (u16)((address | 0xC000) >> 5); + + if (flag == 1) { + for (i = 0; i < (s32)size; i++, buffer += BLOCKSIZE) { + ret = __osContRamWrite(pfs->queue, pfs->channel, address, buffer, 0); + + if (ret != 0) { + break; + } + + if ((++address >= 0x800) && (i < (s32)(size - 1))) { + ret = __osGbpakSetBank(pfs, ++bank); + + if (ret != 0) { + break; + } + + address = 0x600U; + } + } + } else { + for (i = 0; i < (s32)size; i++, buffer += BLOCKSIZE) { + ret = __osContRamRead(pfs->queue, pfs->channel, address, buffer); + + if (ret != 0) { + break; + } + + if (++address >= 0x800 && (i < (s32)(size - 1))) { + ret = __osGbpakSetBank(pfs, ++bank); + + if (ret != 0) { + break; + } + + address = 0x600U; + } + } + } + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + return ret; +} diff --git a/lib/ultralib/src/io/gbpaksetbank.c b/lib/ultralib/src/io/gbpaksetbank.c new file mode 100644 index 0000000..134cad8 --- /dev/null +++ b/lib/ultralib/src/io/gbpaksetbank.c @@ -0,0 +1,35 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 __osGbpakSetBank(OSPfs* pfs, u8 bank) { + int i; + s32 ret; + u8 temp[BLOCKSIZE]; + + if (bank > 2) { + return PFS_ERR_INVALID; + } + + for (i = 0; i < BLOCKSIZE; i++) { + temp[i] = bank; + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, CONT_BLOCK_GB_BANK, temp, FALSE); + + if (ret == PFS_ERR_NEW_PACK) { + ret = osGbpakInit(pfs->queue, pfs, pfs->channel); + + if (ret == 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, CONT_BLOCK_GB_BANK, temp, FALSE); + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + } + } + + if (ret == 0) { + pfs->banks = bank; + } + + return ret; +} diff --git a/lib/ultralib/src/io/motor.c b/lib/ultralib/src/io/motor.c new file mode 100644 index 0000000..df36414 --- /dev/null +++ b/lib/ultralib/src/io/motor.c @@ -0,0 +1,136 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +static OSPifRam __MotorDataBuf[MAXCONTROLLERS]; + +#define READFORMAT(ptr) ((__OSContRamReadFormat*)(ptr)) + +s32 __osMotorAccess(OSPfs* pfs, s32 flag) { + int i; + s32 ret; + u8* ptr = (u8*)&__MotorDataBuf[pfs->channel]; + + if (!(pfs->status & PFS_MOTOR_INITIALIZED)) { + return 5; + } + + __osSiGetAccess(); + __MotorDataBuf[pfs->channel].pifstatus = CONT_CMD_EXE; + ptr += pfs->channel; + + for (i = 0; i < BLOCKSIZE; i++) { + READFORMAT(ptr)->data[i] = flag; + } + + __osContLastCmd = CONT_CMD_END; + __osSiRawStartDma(OS_WRITE, &__MotorDataBuf[pfs->channel]); + osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__MotorDataBuf[pfs->channel]); + osRecvMesg(pfs->queue, NULL, OS_MESG_BLOCK); + + ret = READFORMAT(ptr)->rxsize & CHNL_ERR_MASK; + if (!ret) { + if (!flag) { + if (READFORMAT(ptr)->datacrc != 0) { + ret = PFS_ERR_CONTRFAIL; + } + } else { + if (READFORMAT(ptr)->datacrc != 0xEB) { + ret = PFS_ERR_CONTRFAIL; + } + } + } + + __osSiRelAccess(); + + return ret; +} + +static void _MakeMotorData(int channel, OSPifRam *mdata) { + u8 *ptr = (u8 *)mdata->ramarray; + __OSContRamReadFormat ramreadformat; + int i; + + ramreadformat.dummy = CONT_CMD_NOP; + ramreadformat.txsize = CONT_CMD_WRITE_PAK_TX; + ramreadformat.rxsize = CONT_CMD_WRITE_PAK_RX; + ramreadformat.cmd = CONT_CMD_WRITE_PAK; + ramreadformat.addrh = CONT_BLOCK_RUMBLE >> 3; + ramreadformat.addrl = (u8)(__osContAddressCrc(CONT_BLOCK_RUMBLE) | (CONT_BLOCK_RUMBLE << 5)); + + if (channel != 0) { + for (i = 0; i < channel; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + } + + *READFORMAT(ptr) = ramreadformat; + ptr += sizeof(__OSContRamReadFormat); + ptr[0] = CONT_CMD_END; +} + +s32 osMotorInit(OSMesgQueue *mq, OSPfs *pfs, int channel) +{ + s32 ret; + u8 temp[32]; + + pfs->queue = mq; + pfs->channel = channel; + pfs->activebank = 0xFF; + pfs->status = 0; + + ret = __osPfsSelectBank(pfs, 0xFE); + + if (ret == PFS_ERR_NEW_PACK) { + ret = __osPfsSelectBank(pfs, 0x80); + } + + if (ret != 0) { + return ret; + } + + ret = __osContRamRead(mq, channel, CONT_BLOCK_DETECT, temp); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + if (temp[31] == 254) { + return PFS_ERR_DEVICE; + } + + ret = __osPfsSelectBank(pfs, 0x80); + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + ret = __osContRamRead(mq, channel, CONT_BLOCK_DETECT, temp); + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + if (temp[31] != 0x80) { + return PFS_ERR_DEVICE; + } + + if (!(pfs->status & PFS_MOTOR_INITIALIZED)) { + _MakeMotorData(channel, &__MotorDataBuf[channel]); + } + + pfs->status = PFS_MOTOR_INITIALIZED; + return 0; +} diff --git a/lib/ultralib/src/io/pfsallocatefile.c b/lib/ultralib/src/io/pfsallocatefile.c new file mode 100644 index 0000000..84ef32f --- /dev/null +++ b/lib/ultralib/src/io/pfsallocatefile.c @@ -0,0 +1,148 @@ +#include "PR/os_internal.h" +#include "controller.h" + +#define ROUND_UP_DIVIDE(numerator, denominator) (((numerator) + (denominator) - 1) / (denominator)) + +s32 osPfsAllocateFile(OSPfs *pfs, u16 company_code, u32 game_code, u8 *game_name, u8 *ext_name, int file_size_in_bytes, s32 *file_no) { + int start_page; + int decleared; + int last_page; + int old_last_page = 0; + s32 ret = 0; + int file_size_in_pages; + __OSInode inode; + __OSInode backup_inode; + __OSDir dir; + u8 bank; + u8 old_bank = 0; + int firsttime = 0; + s32 bytes; + __OSInodeUnit fpage; + + if (company_code == 0 || game_code == 0) { + return PFS_ERR_INVALID; + } + + file_size_in_pages = ROUND_UP_DIVIDE(file_size_in_bytes, BLOCKSIZE * PFS_ONE_PAGE); + + ret = osPfsFindFile(pfs, company_code, game_code, game_name, ext_name, file_no); + + if (ret != 0) { + if (ret != PFS_ERR_INVALID) { + return ret; + } + } + + if (*file_no != -1) { + return PFS_ERR_EXIST; + } + + ret = osPfsFreeBlocks(pfs, &bytes); + + if (file_size_in_bytes > bytes) { + return PFS_DATA_FULL; + } + + if (file_size_in_pages == 0) { + return PFS_ERR_INVALID; + } + + ret = osPfsFindFile(pfs, 0, 0, NULL, NULL, file_no); + if (ret != 0) { + if (ret != PFS_ERR_INVALID) { + return ret; + } + } + + if (*file_no == -1) { + return PFS_DIR_FULL; + } + + for (bank = 0; bank < pfs->banks; bank++) { + ERRCK(__osPfsRWInode(pfs, &inode, OS_READ, bank)); + ERRCK(__osPfsDeclearPage(pfs, &inode, file_size_in_pages, &start_page, bank, &decleared, &last_page)); + + if (start_page != -1) { + if (firsttime == 0) { + fpage.inode_t.page = start_page; + fpage.inode_t.bank = bank; + } else { + backup_inode.inode_page[old_last_page].inode_t.bank = bank; + backup_inode.inode_page[old_last_page].inode_t.page = start_page; + ERRCK(__osPfsRWInode(pfs, &backup_inode, OS_WRITE, old_bank)); + } + + if (file_size_in_pages > decleared) { + bcopy(&inode, &backup_inode, sizeof(__OSInode)); + old_last_page = last_page; + old_bank = bank; + file_size_in_pages -= decleared; + firsttime++; + } else { + file_size_in_pages = 0; + ERRCK(__osPfsRWInode(pfs, &inode, PFS_WRITE, bank)); + break; + } + } + } + + if (file_size_in_pages > 0 || start_page == -1) { + return PFS_ERR_INCONSISTENT; + } + + dir.start_page = fpage; + dir.company_code = company_code; + dir.game_code = game_code; + dir.data_sum = 0; + + bcopy(game_name, dir.game_name, PFS_FILE_NAME_LEN); + bcopy(ext_name, dir.ext_name, PFS_FILE_EXT_LEN); + + return __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + *file_no, (u8*)&dir, FALSE); +} + +s32 __osPfsDeclearPage(OSPfs *pfs, __OSInode *inode, int file_size_in_pages, int *first_page, u8 bank, int *decleared, int *last_page) +{ + int j; + int spage; + int old_page; + int i; + s32 ret = 0; + int offset = bank > 0 ? 1 : pfs->inode_start_page; + + for (j = offset; j < ARRLEN(inode->inode_page); j++) { + if (inode->inode_page[j].ipage == 3) { + break; + } + } + + if (j == ARRLEN(inode->inode_page)) { + *first_page = -1; + return ret; + } + + spage = j; + *decleared = 1; + old_page = j++; + + while (file_size_in_pages > *decleared && j < ARRLEN(inode->inode_page)) { + if (inode->inode_page[j].ipage == 3) { + inode->inode_page[old_page].inode_t.bank = bank; + inode->inode_page[old_page].inode_t.page = j; + old_page = j; + (*decleared)++; + } + j++; + } + + *first_page = spage; + + if (j == ARRLEN(inode->inode_page) && file_size_in_pages > *decleared) { + *last_page = old_page; + } else { + inode->inode_page[old_page].ipage = 1; + *last_page = 0; + } + + return ret; +} diff --git a/lib/ultralib/src/io/pfschecker.c b/lib/ultralib/src/io/pfschecker.c new file mode 100644 index 0000000..ee71830 --- /dev/null +++ b/lib/ultralib/src/io/pfschecker.c @@ -0,0 +1,203 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 corrupted_init(OSPfs *pfs, __OSInodeCache *cache); +s32 corrupted(OSPfs *pfs, __OSInodeUnit fpage, __OSInodeCache *cache); + +#define CHECK_IPAGE(p) \ + (((p).ipage >= pfs->inode_start_page) && ((p).inode_t.bank < pfs->banks) && ((p).inode_t.page >= 0x01) && \ + ((p).inode_t.page < 0x80)) + +s32 osPfsChecker(OSPfs *pfs) { + int j; + s32 ret; + __OSInodeUnit next_page; + __OSInode checked_inode; + __OSInode tmp_inode; + __OSDir tmp_dir; + __OSInodeUnit file_next_node[16]; + __OSInodeCache cache; + int fixed = 0; + u8 bank; + u8 oldbank = 254; + s32 cc; + s32 cl; + int offset; + + 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) { + if (tmp_dir.company_code == 0 || tmp_dir.game_code == 0) { + cc = -1; + } else { + next_page = tmp_dir.start_page; + cl = cc = 0; + bank = 255; + + while (CHECK_IPAGE(next_page)) { + if (bank != next_page.inode_t.bank) { + bank = next_page.inode_t.bank; + + if (oldbank != bank) { + ret = __osPfsRWInode(pfs, &tmp_inode, OS_READ, bank); + oldbank = 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 != PFS_EOF) { + bzero(&tmp_dir, sizeof(__OSDir)); + + 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 >= (u16)pfs->inode_start_page) { + 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; + } + + offset = (bank > 0) ? 1 : 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 = PFS_PAGE_NOT_USED; + } + + for (j = 0; j < pfs->dir_size; j++) { + while (file_next_node[j].inode_t.bank == bank && file_next_node[j].ipage >= (u16)pfs->inode_start_page) { + 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 < PFS_INODE_DIST_MAP; i++) { + cache->map[i] = 0; + } + + cache->bank = -1; + for (bank = 0; bank < pfs->banks; bank++) { + offset = bank > 0 ? 1 : 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 & 0x7F) / PFS_SECTOR_SIZE) + ((tpage.inode_t.bank % PFS_BANK_LAPPED_BY) * BLOCKSIZE); + cache->map[n] |= 1 << (bank % PFS_BANK_LAPPED_BY); + } + } + } + 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 / PFS_SECTOR_SIZE) + (fpage.inode_t.bank % PFS_BANK_LAPPED_BY) * BLOCKSIZE; + + for (bank = 0; bank < pfs->banks; bank++) { + offset = bank > 0 ? 1 : pfs->inode_start_page; + + if (bank == fpage.inode_t.bank || cache->map[n] & (1 << (bank % PFS_BANK_LAPPED_BY))) { + 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 (hit >= 2) { + return PFS_ERR_NEW_PACK; + } + } + } + return hit; +} diff --git a/lib/ultralib/src/io/pfsdeletefile.c b/lib/ultralib/src/io/pfsdeletefile.c new file mode 100644 index 0000000..6ca88eb --- /dev/null +++ b/lib/ultralib/src/io/pfsdeletefile.c @@ -0,0 +1,64 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsDeleteFile(OSPfs *pfs, u16 company_code, u32 game_code, u8 *game_name, + u8 *ext_name) { + s32 file_no; + s32 ret; + __OSInode inode; + __OSDir dir; + __OSInodeUnit last_page; + u8 startpage; + u8 bank; + + if (company_code == 0 || game_code == 0) { + return PFS_ERR_INVALID; + } + + ERRCK(osPfsFindFile(pfs, company_code, game_code, game_name, ext_name, &file_no)); + SET_ACTIVEBANK_TO_ZERO; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + file_no, (u8*)&dir)); + + startpage = dir.start_page.inode_t.page; + + for (bank = dir.start_page.inode_t.bank; bank < pfs->banks;) { + ERRCK(__osPfsRWInode(pfs, &inode, OS_READ, bank)); + ERRCK(__osPfsReleasePages(pfs, &inode, startpage, bank, &last_page)); + ERRCK(__osPfsRWInode(pfs, &inode, OS_WRITE, bank)); + + if (last_page.ipage == PFS_EOF) { + break; + } + + bank = last_page.inode_t.bank; + startpage = last_page.inode_t.page; + } + + if (bank >= pfs->banks) { + return PFS_ERR_INCONSISTENT; + } + + bzero(&dir, sizeof(__OSDir)); + + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + file_no, (u8*)&dir, FALSE); + + return ret; +} + +s32 __osPfsReleasePages(OSPfs *pfs, __OSInode *inode, u8 start_page, u8 bank, __OSInodeUnit *last_page) { + __OSInodeUnit next_page; + __OSInodeUnit old_page; + s32 ret = 0; + + next_page.ipage = (bank << 8) + start_page; + + do { + old_page = next_page; + next_page = inode->inode_page[next_page.inode_t.page]; + inode->inode_page[old_page.inode_t.page].ipage = PFS_PAGE_NOT_USED; + } while (next_page.ipage >= pfs->inode_start_page && next_page.inode_t.bank == bank); + + *last_page = next_page; + + return ret; +} diff --git a/lib/ultralib/src/io/pfsfilestate.c b/lib/ultralib/src/io/pfsfilestate.c new file mode 100644 index 0000000..7f5cb8b --- /dev/null +++ b/lib/ultralib/src/io/pfsfilestate.c @@ -0,0 +1,55 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsFileState(OSPfs *pfs, s32 file_no, OSPfsState *state) { + s32 ret; + int pages; + __OSInode inode; + __OSDir dir; + __OSInodeUnit next_page; + u8 bank; + + if (file_no >= pfs->dir_size || file_no < 0) { + return PFS_ERR_INVALID; + } + + PFS_CHECK_STATUS; + ERRCK(__osCheckId(pfs)); + SET_ACTIVEBANK_TO_ZERO; + + ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + file_no, (u8*)&dir)); + + if (dir.company_code == 0 || dir.game_code == 0) { + return PFS_ERR_INVALID; + } + + next_page = dir.start_page; + pages = 0; + bank = 0xFF; + + while (TRUE) { + if (next_page.ipage < pfs->inode_start_page) { + break; + } + + if (next_page.inode_t.bank != bank) { + bank = next_page.inode_t.bank; + ERRCK(__osPfsRWInode(pfs, &inode, PFS_READ, bank)); + } + + pages++; + next_page = inode.inode_page[next_page.inode_t.page]; + } + + if (next_page.ipage != PFS_EOF) { + return PFS_ERR_INCONSISTENT; + } + + state->file_size = pages * PFS_ONE_PAGE * BLOCKSIZE; + state->company_code = dir.company_code; + state->game_code = dir.game_code; + bcopy(&dir.game_name, state->game_name, PFS_FILE_NAME_LEN); + bcopy(&dir.ext_name, state->ext_name, PFS_FILE_EXT_LEN); + + return __osPfsGetStatus(pfs->queue, pfs->channel); +} diff --git a/lib/ultralib/src/io/pfsfreeblocks.c b/lib/ultralib/src/io/pfsfreeblocks.c new file mode 100644 index 0000000..a1fd848 --- /dev/null +++ b/lib/ultralib/src/io/pfsfreeblocks.c @@ -0,0 +1,27 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsFreeBlocks(OSPfs *pfs, s32 *bytes_not_used) { + int j; + int pages = 0; + __OSInode inode; + s32 ret = 0; + u8 bank; + int offset; + + PFS_CHECK_STATUS; + ERRCK(__osCheckId(pfs)); + for (bank = 0; bank < pfs->banks; bank++) { + ERRCK(__osPfsRWInode(pfs, &inode, OS_READ, bank)); + offset = ((bank > 0) ? 1 : pfs->inode_start_page); + + for (j = offset; j < ARRLEN(inode.inode_page); j++) { + if (inode.inode_page[j].ipage == PFS_PAGE_NOT_USED) { + pages++; + } + } + } + + *bytes_not_used = pages * PFS_ONE_PAGE * BLOCKSIZE; + return 0; +} diff --git a/lib/ultralib/src/io/pfsgetlabel.c b/lib/ultralib/src/io/pfsgetlabel.c new file mode 100644 index 0000000..960bd30 --- /dev/null +++ b/lib/ultralib/src/io/pfsgetlabel.c @@ -0,0 +1,23 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsGetLabel(OSPfs *pfs, u8 *label, int *len) { + int i; + + if (label == NULL) { + return PFS_ERR_INVALID; + } + + PFS_CHECK_ID; + + for (i = 0; i < ARRLEN(pfs->label); i++) { + if(*(pfs->label + i) == 0) { + break; + } + + *label++ = *(pfs->label + i); + } + + *len = i; + return 0; +} diff --git a/lib/ultralib/src/io/pfsgetstatus.c b/lib/ultralib/src/io/pfsgetstatus.c new file mode 100644 index 0000000..6640728 --- /dev/null +++ b/lib/ultralib/src/io/pfsgetstatus.c @@ -0,0 +1,78 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +void __osPfsRequestOneChannel(int channel, u8 cmd); +void __osPfsGetOneChannelData(int channel, OSContStatus *data); + +s32 __osPfsGetStatus(OSMesgQueue *queue, int channel) { + s32 ret = 0; + OSMesg dummy; + OSContStatus data; + + __osPfsInodeCacheBank = 250; + + __osPfsRequestOneChannel(channel, 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); + + __osPfsGetOneChannelData(channel, &data); + + if (((data.status & CONT_CARD_ON) != 0) && ((data.status & CONT_CARD_PULL) != 0)) { + return PFS_ERR_NEW_PACK; + } else if ((data.errno != 0) || ((data.status & CONT_CARD_ON) == 0)) { + return PFS_ERR_NOPACK; + } else if ((data.status & CONT_ADDR_CRC_ER) != 0) { + return PFS_ERR_CONTRFAIL; + } + + return ret; +} + +void __osPfsRequestOneChannel(int channel, u8 cmd) { + u8 *ptr; + __OSContRequesFormatShort requestformat; + int i; + + __osContLastCmd = CONT_CMD_END; + __osPfsPifRam.pifstatus = CONT_CMD_READ_BUTTON; + + ptr = (u8 *)&__osPfsPifRam; + + 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; + + for (i = 0; i < channel; i++) { + *ptr++ = CONT_CMD_REQUEST_STATUS; + } + + *(__OSContRequesFormatShort *)ptr = requestformat; + ptr += sizeof(__OSContRequesFormatShort); + *ptr = CONT_CMD_END; +} + +void __osPfsGetOneChannelData(int channel, OSContStatus *data) { + u8 *ptr = (u8*)&__osPfsPifRam; + __OSContRequesFormatShort requestformat; + int i; + + for (i = 0; i < channel; i++) { + ptr++; + } + + requestformat = *(__OSContRequesFormatShort *)ptr; + data->errno = CHNL_ERR(requestformat); + + if (data->errno == 0) { + data->type = (requestformat.typel << 8) | (requestformat.typeh); + data->status = requestformat.status; + } +} diff --git a/lib/ultralib/src/io/pfsinit.c b/lib/ultralib/src/io/pfsinit.c new file mode 100644 index 0000000..e290cda --- /dev/null +++ b/lib/ultralib/src/io/pfsinit.c @@ -0,0 +1,25 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +s32 osPfsInit(OSMesgQueue *queue, OSPfs *pfs, int channel) { + s32 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; +} diff --git a/lib/ultralib/src/io/pfsinitpak.c b/lib/ultralib/src/io/pfsinitpak.c new file mode 100644 index 0000000..927636f --- /dev/null +++ b/lib/ultralib/src/io/pfsinitpak.c @@ -0,0 +1,101 @@ +#include "PR/os_internal.h" +#include "controller.h" + +static s32 __osPfsCheckRamArea(OSPfs* pfs); + +s32 osPfsInitPak(OSMesgQueue* queue, OSPfs* pfs, int channel) { + s32 ret; + u16 sum; + u16 isum; + u8 temp[BLOCKSIZE]; + __OSPackId* id; + __OSPackId newid; + + __osSiGetAccess(); + + ret = __osPfsGetStatus(queue, channel); + + __osSiRelAccess(); + + if (ret != 0) { + return ret; + } + + pfs->queue = queue; + pfs->channel = channel; + pfs->status = 0; + + ERRCK(__osPfsCheckRamArea(pfs)); + ERRCK(__osPfsSelectBank(pfs, 0)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)); + + __osIdCheckSum((u16*)temp, &sum, &isum); + id = (__OSPackId*)temp; + + if ((id->checksum != sum) || (id->inverted_checksum != isum)) { + ret = __osCheckPackId(pfs, id); + + if (ret != 0) { + pfs->status |= PFS_ID_BROKEN; + return ret; + } + } + + if (!(id->deviceid & 1)) { + ret = __osRepairPackId(pfs, id, &newid); + + if (ret != 0) { + if (ret == PFS_ERR_ID_FATAL) { + pfs->status |= PFS_ID_BROKEN; + } + return ret; + } + + id = &newid; + + if (!(id->deviceid & 1)) { + return PFS_ERR_DEVICE; + } + } + + bcopy(id, pfs->id, BLOCKSIZE); + + pfs->version = id->version; + pfs->banks = id->banks; + pfs->inode_start_page = 1 + DEF_DIR_PAGES + (2 * pfs->banks); + pfs->dir_size = DEF_DIR_PAGES * PFS_ONE_PAGE; + pfs->inode_table = 1 * PFS_ONE_PAGE; + pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE; + pfs->dir_table = pfs->minode_table + (pfs->banks * PFS_ONE_PAGE); + + ERRCK(__osContRamRead(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label)); + + ret = osPfsChecker(pfs); + pfs->status |= PFS_INITIALIZED; + + return ret; +} + +static s32 __osPfsCheckRamArea(OSPfs* pfs) { + s32 i = 0; + s32 ret = 0; + u8 temp1[BLOCKSIZE]; + u8 temp2[BLOCKSIZE]; + u8 save[BLOCKSIZE]; + + ERRCK(__osPfsSelectBank(pfs, 0)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, save)); + + for (i = 0; i < BLOCKSIZE; i++) { + temp1[i] = i; + } + + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, 0, temp1, FALSE)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, temp2)); + + if (bcmp(temp1, temp2, BLOCKSIZE) != 0) { + return PFS_ERR_DEVICE; + } + + return __osContRamWrite(pfs->queue, pfs->channel, 0, save, FALSE); +} diff --git a/lib/ultralib/src/io/pfsisplug.c b/lib/ultralib/src/io/pfsisplug.c new file mode 100644 index 0000000..71a18d9 --- /dev/null +++ b/lib/ultralib/src/io/pfsisplug.c @@ -0,0 +1,96 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "controller.h" + +OSPifRam __osPfsPifRam ALIGNED(16); + +s32 osPfsIsPlug(OSMesgQueue* mq, u8* pattern) { + s32 ret = 0; + OSMesg msg; + u8 bitpattern; + OSContStatus contData[MAXCONTROLLERS]; + s32 channel; + u8 bits = 0; + s32 crcErrorCount = 3; + + __osSiGetAccess(); + + do { + __osPfsRequestData(CONT_CMD_REQUEST_STATUS); + + ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, &msg, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, &msg, OS_MESG_BLOCK); + + __osPfsGetInitData(&bitpattern, &contData[0]); + + for (channel = 0; channel < __osMaxControllers; channel++) { + if ((contData[channel].status & CONT_ADDR_CRC_ER) == 0) { + crcErrorCount--; + break; + } + } + + if (channel == __osMaxControllers) { + crcErrorCount = 0; + } + } while (crcErrorCount > 0); + + for (channel = 0; channel < __osMaxControllers; channel++) { + if ((contData[channel].errno == 0) && ((contData[channel].status & CONT_CARD_ON) != 0)) { + bits |= (1 << channel); + } + } + __osSiRelAccess(); + *pattern = bits; + return ret; +} + +void __osPfsRequestData(u8 cmd) { + u8* ptr = (u8*)&__osPfsPifRam; + __OSContRequesFormat requestformat; + int i; + + __osContLastCmd = cmd; + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + 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 = 0; + + ptr = (u8*)&__osPfsPifRam; + + for (i = 0; i < __osMaxControllers; i++, ptr += sizeof(requestformat), data++) { + requestformat = *((__OSContRequesFormat*)ptr); + data->errno = CHNL_ERR(requestformat); + + if (data->errno) { + continue; + } + + data->type = ((requestformat.typel << 8) | requestformat.typeh); + data->status = requestformat.status; + bits |= (1 << i); + } + *pattern = bits; +} diff --git a/lib/ultralib/src/io/pfsnumfiles.c b/lib/ultralib/src/io/pfsnumfiles.c new file mode 100644 index 0000000..e4480bd --- /dev/null +++ b/lib/ultralib/src/io/pfsnumfiles.c @@ -0,0 +1,24 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsNumFiles(OSPfs *pfs, s32 *max_files, s32 *files_used) { + int j; + s32 ret; + __OSDir dir; + int files = 0; + + PFS_CHECK_STATUS; + ERRCK(__osCheckId(pfs)); + SET_ACTIVEBANK_TO_ZERO; + + for (j = 0; j < pfs->dir_size; j++) { + ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&dir)); + + if (dir.company_code != 0 && dir.game_code != 0) { + files++; + } + } + *files_used = files; + *max_files = pfs->dir_size; + return __osPfsGetStatus(pfs->queue, pfs->channel); +} diff --git a/lib/ultralib/src/io/pfsreadwritefile.c b/lib/ultralib/src/io/pfsreadwritefile.c new file mode 100644 index 0000000..14a6e45 --- /dev/null +++ b/lib/ultralib/src/io/pfsreadwritefile.c @@ -0,0 +1,119 @@ +#include "PR/os_internal.h" +#include "controller.h" + +static s32 __osPfsGetNextPage(OSPfs *pfs, u8 *bank, __OSInode *inode, __OSInodeUnit *page) { + s32 ret; + + if (page->inode_t.bank != *bank) { + *bank = page->inode_t.bank; + ERRCK(__osPfsRWInode(pfs, inode, 0, *bank)); + } + + *page = inode->inode_page[page->inode_t.page]; + + if (page->ipage < pfs->inode_start_page || + page->inode_t.bank >= pfs->banks || + page->inode_t.page <= 0 || + page->inode_t.page >= ARRLEN(inode->inode_page)) { + + if (page->ipage == 1) { + return PFS_ERR_INVALID; + } + + return PFS_ERR_INCONSISTENT; + } + return 0; +} +s32 osPfsReadWriteFile(OSPfs *pfs, s32 file_no, u8 flag, int offset, int size_in_bytes, u8 *data_buffer) { + s32 ret; + __OSDir dir; + __OSInode inode; + __OSInodeUnit cur_page; + int cur_block; + int siz_block; + u8 *buffer; + u8 bank; + u16 blockno; + + if (file_no >= pfs->dir_size || file_no < 0) { + return PFS_ERR_INVALID; + } + + if (size_in_bytes <= 0 || ((size_in_bytes & (BLOCKSIZE - 1)) != 0)) { + return PFS_ERR_INVALID; + } + + if (offset < 0 || ((offset & (BLOCKSIZE - 1)) != 0)) { + return PFS_ERR_INVALID; + } + + PFS_CHECK_STATUS; + PFS_CHECK_ID; + SET_ACTIVEBANK_TO_ZERO; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + file_no, (u8*)&dir)); + + if (dir.company_code == 0 || dir.game_code == 0) { + return PFS_ERR_INVALID; + } + + if (dir.start_page.ipage < pfs->inode_start_page || + dir.start_page.inode_t.bank >= pfs->banks || + dir.start_page.inode_t.page <= 0 || + dir.start_page.inode_t.page >= ARRLEN(inode.inode_page)) { + if ((dir.start_page.ipage == 1)) { + return PFS_ERR_INVALID; + } + + return PFS_ERR_INCONSISTENT; + } + + if (flag == PFS_READ && (dir.status & DIR_STATUS_OCCUPIED) == 0) { + return PFS_ERR_BAD_DATA; + } + + bank = -1; + cur_block = offset / BLOCKSIZE; + cur_page = dir.start_page; + + while (cur_block >= PFS_ONE_PAGE) { + ERRCK(__osPfsGetNextPage(pfs, &bank, &inode, &cur_page)); + cur_block -= PFS_ONE_PAGE; + } + + siz_block = size_in_bytes / BLOCKSIZE; + buffer = data_buffer; + + while (siz_block > 0) { + if (cur_block == PFS_ONE_PAGE) { + ERRCK(__osPfsGetNextPage(pfs, &bank, &inode, &cur_page)); + cur_block = 0; + } + + if (pfs->activebank != cur_page.inode_t.bank) { + ERRCK(__osPfsSelectBank(pfs, cur_page.inode_t.bank)); + } + + blockno = cur_page.inode_t.page * PFS_ONE_PAGE + cur_block; + + if (flag == OS_READ) { + ret = __osContRamRead(pfs->queue, pfs->channel, blockno, buffer); + } else { + ret = __osContRamWrite(pfs->queue, pfs->channel, blockno, buffer, FALSE); + } + + if (ret != 0) { + return ret; + } + buffer += BLOCKSIZE; + cur_block++; + siz_block--; + } + + if (flag == PFS_WRITE && (dir.status & DIR_STATUS_OCCUPIED) == 0) { + dir.status |= DIR_STATUS_OCCUPIED; + SET_ACTIVEBANK_TO_ZERO; + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + file_no, (u8*)&dir, FALSE)); + } + + return __osPfsGetStatus(pfs->queue, pfs->channel); +} diff --git a/lib/ultralib/src/io/pfsreformat.c b/lib/ultralib/src/io/pfsreformat.c new file mode 100644 index 0000000..cbd4b6a --- /dev/null +++ b/lib/ultralib/src/io/pfsreformat.c @@ -0,0 +1,70 @@ +#include "PR/os_internal.h" +#include "controller.h" +#include "siint.h" + +s32 osPfsReFormat(OSPfs *pfs, OSMesgQueue *queue, int channel) { + int j; + int i; + __OSInode inode; + u8 tmp_data[32]; + u8 *ptr; + s32 ret; + __osSiGetAccess(); + ret = __osPfsGetStatus(queue, channel); + + if (ret != 0) { + __osSiRelAccess(); + return ret; + } + + pfs->status ^= PFS_INITIALIZED; + pfs->queue = queue; + pfs->channel = channel; + __osSiRelAccess(); + ERRCK(__osGetId(pfs)); + + SET_ACTIVEBANK_TO_ZERO; + + for (j = 0; j < ARRLEN(tmp_data); j++) { + tmp_data[j] = 0; + } + + for (j = 0; j < pfs->dir_size; j++) + { + ERRCK(__osContRamWrite(queue, channel, pfs->dir_table + j, tmp_data, FALSE)); + } + + for (j = 0; j < pfs->inode_start_page; j++) { + inode.inode_page[j].ipage = 0; + } + + for (j = pfs->inode_start_page; j < ARRLEN(inode.inode_page); j++) { + inode.inode_page[j].ipage = 3; + } + + inode.inode_page[0].ipage = __osSumcalc((u8*)(inode.inode_page + pfs->inode_start_page), + (ARRLEN(inode.inode_page) - pfs->inode_start_page) * sizeof(__OSInodeUnit)); + ptr = (u8 *)&inode; + + for (j = 0; j < PFS_ONE_PAGE; j++) { + ERRCK(__osContRamWrite(queue, channel, pfs->inode_table + j, ptr + j * BLOCKSIZE, FALSE)); + ERRCK(__osContRamWrite(queue, channel, pfs->minode_table + j, ptr + j * BLOCKSIZE, FALSE)); + } + + for (i = 1; i < pfs->banks; i++) { + for (j = 1; j < ARRLEN(inode.inode_page); j++) { + inode.inode_page[j].ipage = 3; + } + + inode.inode_page[0].ipage = __osSumcalc((u8*)(inode.inode_page + 1), + (ARRLEN(inode.inode_page) - 1) * sizeof(__OSInodeUnit)); + ptr = (u8 *)&inode; + + for (j = 0; j < PFS_ONE_PAGE; j++) { + ERRCK(__osContRamWrite(queue, channel, pfs->inode_table + i * PFS_ONE_PAGE + j, ptr + j * BLOCKSIZE, FALSE)); + ERRCK(__osContRamWrite(queue, channel, pfs->minode_table + i * PFS_ONE_PAGE + j, ptr + j * BLOCKSIZE, FALSE)); + } + } + + return 0; +} diff --git a/lib/ultralib/src/io/pfsrepairid.c b/lib/ultralib/src/io/pfsrepairid.c new file mode 100644 index 0000000..f29590a --- /dev/null +++ b/lib/ultralib/src/io/pfsrepairid.c @@ -0,0 +1,18 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsRepairId(OSPfs *pfs) { + s32 ret = 0; + + if ((pfs->status & (PFS_INITIALIZED | PFS_ID_BROKEN))) { + ret = __osGetId(pfs); + + if (ret == 0) { + pfs->status &= ~(PFS_ID_BROKEN); + } + } else { + ret = PFS_ERR_INVALID; + } + + return ret; +} diff --git a/lib/ultralib/src/io/pfssearchfile.c b/lib/ultralib/src/io/pfssearchfile.c new file mode 100644 index 0000000..04a4155 --- /dev/null +++ b/lib/ultralib/src/io/pfssearchfile.c @@ -0,0 +1,51 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsFindFile(OSPfs *pfs, u16 company_code, u32 game_code, u8 *game_name, u8 *ext_name, s32 *file_no) { + s32 j; + int i; + __OSDir dir; + s32 ret = 0; + int fail; + + if (!(pfs->status & PFS_INITIALIZED)) { + return PFS_ERR_INVALID; + } + + ERRCK(__osCheckId(pfs)); + + for (j = 0; j < pfs->dir_size; j++) { + ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&dir)); + ERRCK(__osPfsGetStatus(pfs->queue, pfs->channel)); + + if ((dir.company_code == company_code) && dir.game_code == game_code) { + fail = FALSE; + + if (game_name != NULL) { + for (i = 0; i < ARRLEN(dir.game_name); i++) { + if (dir.game_name[i] != game_name[i]) { + fail = TRUE; + break; + } + } + } + + if (ext_name != NULL && !fail) { + for (i = 0; i < ARRLEN(dir.ext_name); i++) { + if (dir.ext_name[i] != ext_name[i]) { + fail = TRUE; + break; + } + } + } + + if (!fail) { + *file_no = j; + return ret; + } + } + } + + *file_no = -1; + return PFS_ERR_INVALID; +} diff --git a/lib/ultralib/src/io/pfsselectbank.c b/lib/ultralib/src/io/pfsselectbank.c new file mode 100644 index 0000000..fb0ab48 --- /dev/null +++ b/lib/ultralib/src/io/pfsselectbank.c @@ -0,0 +1,20 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 __osPfsSelectBank(OSPfs* pfs, u8 bank) { + u8 temp[BLOCKSIZE]; + int i; + s32 ret = 0; + + for (i = 0; i < BLOCKSIZE; i++) { + temp[i] = bank; + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, CONT_BLOCK_DETECT, temp, FALSE); + + if (ret == 0) { + pfs->activebank = bank; + } + + return ret; +} diff --git a/lib/ultralib/src/io/pfssetlabel.c b/lib/ultralib/src/io/pfssetlabel.c new file mode 100644 index 0000000..a0584cf --- /dev/null +++ b/lib/ultralib/src/io/pfssetlabel.c @@ -0,0 +1,31 @@ +#include "PR/os_internal.h" +#include "controller.h" + +s32 osPfsSetLabel(OSPfs *pfs, u8 *label) { + int i; + s32 ret; + + if (!(pfs->status & PFS_INITIALIZED)) { + return PFS_ERR_INVALID; + } + + ERRCK(__osCheckId(pfs)); + + if (label != NULL) { + for (i = 0; i < ARRLEN(pfs->label); i++) { + if (*label == 0) { + break; + } + + *(pfs->label + i) = *label++; + } + } + + if (pfs->activebank != 0) { + ret = (__osPfsSelectBank(pfs, 0)); + if (ret == 0) { + ret = (__osContRamWrite(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label, FALSE)); + } + } + return ret; +} diff --git a/lib/ultralib/src/io/pi.c b/lib/ultralib/src/io/pi.c new file mode 100644 index 0000000..1c350c5 --- /dev/null +++ b/lib/ultralib/src/io/pi.c @@ -0,0 +1,13 @@ + +#include "PR/os_internal.h" +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +int __osPiDeviceBusy() { + register u32 stat = IO_READ(PI_STATUS_REG); + if (stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) + return 1; + return 0; +} diff --git a/lib/ultralib/src/io/piacs.c b/lib/ultralib/src/io/piacs.c new file mode 100644 index 0000000..03ab11e --- /dev/null +++ b/lib/ultralib/src/io/piacs.c @@ -0,0 +1,24 @@ +#include "macros.h" +#include "PR/os_internal.h" + +#define PI_Q_BUF_LEN 1 +u32 __osPiAccessQueueEnabled = 0; +OSMesgQueue __osPiAccessQueue ALIGNED(8); +static OSMesg piAccessBuf[PI_Q_BUF_LEN]; + +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); +} diff --git a/lib/ultralib/src/io/pidma.c b/lib/ultralib/src/io/pidma.c new file mode 100644 index 0000000..077f13a --- /dev/null +++ b/lib/ultralib/src/io/pidma.c @@ -0,0 +1,30 @@ +#include "PR/os_internal.h" +#include "piint.h" + +s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, u32 devAddr, void *dramAddr, u32 size, OSMesgQueue *mq) { + register s32 ret; + if (!__osPiDevMgr.active) { + return -1; + } + + if (direction == OS_READ) { + mb->hdr.type = OS_MESG_TYPE_DMAREAD; + } else { + mb->hdr.type = OS_MESG_TYPE_DMAWRITE; + } + + mb->hdr.pri = priority; + mb->hdr.retQueue = mq; + mb->dramAddr = dramAddr; + mb->devAddr = devAddr; + mb->size = size; + mb->piHandle = NULL; + + if (priority == OS_MESG_PRI_HIGH) { + ret = osJamMesg(osPiGetCmdQueue(), (OSMesg)mb, OS_MESG_NOBLOCK); + } else { + ret = osSendMesg(osPiGetCmdQueue(), (OSMesg)mb, OS_MESG_NOBLOCK); + } + + return ret; +} diff --git a/lib/ultralib/src/io/pigetcmdq.c b/lib/ultralib/src/io/pigetcmdq.c new file mode 100644 index 0000000..809cdb2 --- /dev/null +++ b/lib/ultralib/src/io/pigetcmdq.c @@ -0,0 +1,10 @@ +#include "PR/os_internal.h" +#include "piint.h" + +OSMesgQueue *osPiGetCmdQueue(void) { + if (!__osPiDevMgr.active) { + return NULL; + } + + return __osPiDevMgr.cmdQueue; +} diff --git a/lib/ultralib/src/io/pigetstat.c b/lib/ultralib/src/io/pigetstat.c new file mode 100644 index 0000000..43e9a27 --- /dev/null +++ b/lib/ultralib/src/io/pigetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 osPiGetStatus() { + return IO_READ(PI_STATUS_REG); +} diff --git a/lib/ultralib/src/io/pigettype.c b/lib/ultralib/src/io/pigettype.c new file mode 100644 index 0000000..f918306 --- /dev/null +++ b/lib/ultralib/src/io/pigettype.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osPiGetDeviceType() { + return osRomType; +} diff --git a/lib/ultralib/src/io/piint.h b/lib/ultralib/src/io/piint.h new file mode 100644 index 0000000..734fdde --- /dev/null +++ b/lib/ultralib/src/io/piint.h @@ -0,0 +1,154 @@ +#ifndef _PIINT_H_ +#define _PIINT_H_ + +#include "PR/os_internal.h" +#include "PR/rcp.h" + +//https://github.com/LuigiBlood/64dd/wiki/Memory-Map + +#define LEO_BASE_REG 0x05000000 + +#define LEO_CMD (LEO_BASE_REG + 0x508) +#define LEO_STATUS (LEO_BASE_REG + 0x508) + +#define LEO_BM_CTL (LEO_BASE_REG + 0x510) +#define LEO_BM_STATUS (LEO_BASE_REG + 0x510) + +#define LEO_SEQ_CTL (LEO_BASE_REG + 0x518) +#define LEO_SEQ_STATUS (LEO_BASE_REG + 0x518) + +#define LEO_C2_BUFF (LEO_BASE_REG + 0x000) //C2 Sector Buffer +#define LEO_SECTOR_BUFF (LEO_BASE_REG + 0x400) //Data Sector Buffer +#define LEO_DATA (LEO_BASE_REG + 0x500) //Data +#define LEO_MISC_REG (LEO_BASE_REG + 0x504) //Misc Register +#define LEO_CUR_TK (LEO_BASE_REG + 0x50C) //Current Track +#define LEO_ERR_SECTOR (LEO_BASE_REG + 0x514) //Sector Error Status +#define LEO_CUR_SECTOR (LEO_BASE_REG + 0x51C) //Current Sector +#define LEO_HARD_RESET (LEO_BASE_REG + 0x520) //Hard Reset +#define LEO_C1_S0 (LEO_BASE_REG + 0x524) //C1 +#define LEO_HOST_SECBYTE (LEO_BASE_REG + 0x528) //Sector Size (in bytes) +#define LEO_C1_S2 (LEO_BASE_REG + 0x52C) //C1 +#define LEO_SEC_BYTE (LEO_BASE_REG + 0x530) //Sectors per Block, Full Size +#define LEO_C1_S4 (LEO_BASE_REG + 0x534) //C1 +#define LEO_C1_S6 (LEO_BASE_REG + 0x538) //C1 +#define LEO_CUR_ADDR (LEO_BASE_REG + 0x53C) //Current Address? +#define LEO_ID_REG (LEO_BASE_REG + 0x540) //ID +#define LEO_TEST_REG (LEO_BASE_REG + 0x544) //Test Read +#define LEO_TEST_PIN_SEL (LEO_BASE_REG + 0x548) //Test Write +#define LEO_RAM_ADDR (LEO_BASE_REG + 0x580) //Microsequencer RAM + +#define LEO_STATUS_PRESENCE_MASK 0xFFFF + +#define LEO_STATUS_DATA_REQUEST 0x40000000 +#define LEO_STATUS_C2_TRANSFER 0x10000000 +#define LEO_STATUS_BUFFER_MANAGER_ERROR 0x08000000 +#define LEO_STATUS_BUFFER_MANAGER_INTERRUPT 0x04000000 +#define LEO_STATUS_MECHANIC_INTERRUPT 0x02000000 +#define LEO_STATUS_DISK_PRESENT 0x01000000 +#define LEO_STATUS_BUSY_STATE 0x00800000 +#define LEO_STATUS_RESET_STATE 0x00400000 +#define LEO_STATUS_MOTOR_NOT_SPINNING 0x00100000 +#define LEO_STATUS_HEAD_RETRACTED 0x00080000 +#define LEO_STATUS_WRITE_PROTECT_ERROR 0x00040000 +#define LEO_STATUS_MECHANIC_ERROR 0x00020000 +#define LEO_STATUS_DISK_CHANGE 0x00010000 + +#define LEO_STATUS_MODE_MASK (LEO_STATUS_MOTOR_NOT_SPINNING | LEO_STATUS_HEAD_RETRACTED) +#define LEO_STATUS_MODE_SLEEP (LEO_STATUS_MOTOR_NOT_SPINNING | LEO_STATUS_HEAD_RETRACTED) +#define LEO_STATUS_MODE_STANDBY (LEO_STATUS_HEAD_RETRACTED) +#define LEO_STATUS_MODE_ACTIVE 0 + +#define LEO_CUR_TK_INDEX_LOCK 0x60000000 + +#define LEO_BM_STATUS_RUNNING 0x80000000 //Running +#define LEO_BM_STATUS_ERROR 0x04000000 //Error +#define LEO_BM_STATUS_MICRO 0x02000000 //Micro Status? +#define LEO_BM_STATUS_BLOCK 0x01000000 //Block Transfer +#define LEO_BM_STATUS_C1CORRECTION 0x00800000 //C1 Correction +#define LEO_BM_STATUS_C1DOUBLE 0x00400000 //C1 Double +#define LEO_BM_STATUS_C1SINGLE 0x00200000 //C1 Single +#define LEO_BM_STATUS_C1ERROR 0x00010000 //C1 Error + +#define LEO_BM_CTL_START 0x80000000 //Start Buffer Manager +#define LEO_BM_CTL_MODE 0x40000000 //Buffer Manager Mode +#define LEO_BM_CTL_IMASK 0x20000000 //BM Interrupt Mask +#define LEO_BM_CTL_RESET 0x10000000 //Buffer Manager Reset +#define LEO_BM_CTL_DISABLE_OR 0x08000000 //Disable OR Check? +#define LEO_BM_CTL_DISABLE_C1 0x04000000 //Disable C1 Correction +#define LEO_BM_CTL_BLOCK 0x02000000 //Block Transfer +#define LEO_BM_CTL_CLR_MECHANIC_INTR 0x01000000 //Mechanic Interrupt Reset + +#define LEO_BM_CTL_CONTROL_MASK 0xFF000000 +#define LEO_BM_CTL_SECTOR_MASK 0x00FF0000 +#define LEO_BM_CTL_SECTOR_SHIFT 16 + +#define LEO_CMD_TYPE_0 0 //TODO: name +#define LEO_CMD_TYPE_1 1 //TODO: name +#define LEO_CMD_TYPE_2 2 //TODO: name + +#define LEO_ERROR_GOOD 0 +#define LEO_ERROR_4 4 //maybe busy? +#define LEO_ERROR_22 22 // +#define LEO_ERROR_23 23 //unrecovered read error? +#define LEO_ERROR_24 24 //no reference position found? +#define LEO_ERROR_29 29 // + +extern OSDevMgr __osPiDevMgr; +extern OSPiHandle *__osCurrentHandle[2]; +extern OSPiHandle CartRomHandle; +extern OSPiHandle LeoDiskHandle; +extern OSMesgQueue __osPiAccessQueue; +extern u32 __osPiAccessQueueEnabled; + +int __osPiDeviceBusy(void); +void __osDevMgrMain(void *); +void __osPiCreateAccessQueue(void); +void __osPiRelAccess(void); +void __osPiGetAccess(void); +s32 __osPiRawStartDma(s32, u32 , void *, u32 ); +s32 __osPiRawWriteIo(u32, u32); +s32 __osPiRawReadIo(u32, u32 *); +s32 __osEPiRawWriteIo(OSPiHandle *, u32 , u32); +s32 __osEPiRawReadIo(OSPiHandle *, u32 , u32 *); +s32 __osEPiRawStartDma(OSPiHandle *, s32 , u32 , void *, u32 ); +OSMesgQueue *osPiGetCmdQueue(void); + +#define WAIT_ON_IOBUSY(stat) \ + while (stat = IO_READ(PI_STATUS_REG), stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) \ + ; \ + (void)0 + +#define UPDATE_REG(pihandle, 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]->type != pihandle->type) \ + { \ + OSPiHandle *cHandle = __osCurrentHandle[domain]; \ + if (domain == PI_DOMAIN1) \ + { \ + UPDATE_REG(pihandle, PI_BSD_DOM1_LAT_REG, latency); \ + UPDATE_REG(pihandle, PI_BSD_DOM1_PGS_REG, pageSize); \ + UPDATE_REG(pihandle, PI_BSD_DOM1_RLS_REG, relDuration); \ + UPDATE_REG(pihandle, PI_BSD_DOM1_PWD_REG, pulse); \ + } \ + else \ + { \ + UPDATE_REG(pihandle, PI_BSD_DOM2_LAT_REG, latency); \ + UPDATE_REG(pihandle, PI_BSD_DOM2_PGS_REG, pageSize); \ + UPDATE_REG(pihandle, PI_BSD_DOM2_RLS_REG, relDuration); \ + UPDATE_REG(pihandle, PI_BSD_DOM2_PWD_REG, pulse); \ + } \ + cHandle->type = pihandle->type; \ + cHandle->latency = pihandle->latency; \ + cHandle->pageSize = pihandle->pageSize; \ + cHandle->relDuration = pihandle->relDuration; \ + cHandle->pulse = pihandle->pulse; \ + }(void)0 + +#endif diff --git a/lib/ultralib/src/io/pimgr.c b/lib/ultralib/src/io/pimgr.c new file mode 100644 index 0000000..c757532 --- /dev/null +++ b/lib/ultralib/src/io/pimgr.c @@ -0,0 +1,53 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "piint.h" + +OSDevMgr __osPiDevMgr = {0}; +OSPiHandle *__osPiTable = NULL; +OSPiHandle __Dom1SpeedParam ALIGNED(8); +OSPiHandle __Dom2SpeedParam ALIGNED(8); +OSPiHandle *__osCurrentHandle[2] ALIGNED(8) = {&__Dom1SpeedParam, &__Dom2SpeedParam}; +static OSThread piThread; +static char piThreadStack[OS_PIM_STACKSIZE]; +static OSMesgQueue piEventQueue; +static OSMesg piEventBuf[1]; + +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); + } + } +} diff --git a/lib/ultralib/src/io/pirawdma.c b/lib/ultralib/src/io/pirawdma.c new file mode 100644 index 0000000..d766064 --- /dev/null +++ b/lib/ultralib/src/io/pirawdma.c @@ -0,0 +1,25 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +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; +} diff --git a/lib/ultralib/src/io/pirawread.c b/lib/ultralib/src/io/pirawread.c new file mode 100644 index 0000000..8531d17 --- /dev/null +++ b/lib/ultralib/src/io/pirawread.c @@ -0,0 +1,13 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osPiRawReadIo(u32 devAddr, u32* data) { + register u32 stat; + + WAIT_ON_IOBUSY(stat); + *data = IO_READ((u32)osRomBase | devAddr); + + return 0; +} diff --git a/lib/ultralib/src/io/pirawwrite.c b/lib/ultralib/src/io/pirawwrite.c new file mode 100644 index 0000000..5e9d7c5 --- /dev/null +++ b/lib/ultralib/src/io/pirawwrite.c @@ -0,0 +1,13 @@ +#include "piint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osPiRawWriteIo(u32 devAddr, u32 data) { + register u32 stat; + + WAIT_ON_IOBUSY(stat); + IO_WRITE((u32)osRomBase | devAddr, data); + + return 0; +} diff --git a/lib/ultralib/src/io/piread.c b/lib/ultralib/src/io/piread.c new file mode 100644 index 0000000..2fed7a6 --- /dev/null +++ b/lib/ultralib/src/io/piread.c @@ -0,0 +1,13 @@ +#include "piint.h" + +s32 __osPiRawReadIo(u32, u32*); + +s32 osPiReadIo(u32 devAddr, u32* data) { + register s32 ret; + + __osPiGetAccess(); + ret = __osPiRawReadIo(devAddr, data); + __osPiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/io/piwrite.c b/lib/ultralib/src/io/piwrite.c new file mode 100644 index 0000000..9935331 --- /dev/null +++ b/lib/ultralib/src/io/piwrite.c @@ -0,0 +1,13 @@ +#include "piint.h" + +s32 __osPiRawWriteIo(u32, u32); + +s32 osPiWriteIo(u32 devAddr, u32 data) { + register s32 ret; + + __osPiGetAccess(); + ret = __osPiRawWriteIo(devAddr, data); + __osPiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/io/si.c b/lib/ultralib/src/io/si.c new file mode 100644 index 0000000..f97691b --- /dev/null +++ b/lib/ultralib/src/io/si.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "siint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +int __osSiDeviceBusy() { + register u32 stat = IO_READ(SI_STATUS_REG); + + if (stat & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY)) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/ultralib/src/io/siacs.c b/lib/ultralib/src/io/siacs.c new file mode 100644 index 0000000..f515c49 --- /dev/null +++ b/lib/ultralib/src/io/siacs.c @@ -0,0 +1,24 @@ +#include "macros.h" +#include "PR/os_internal.h" + +#define SI_Q_BUF_LEN 1 +static OSMesg siAccessBuf[SI_Q_BUF_LEN] ALIGNED(8); +OSMesgQueue __osSiAccessQueue ALIGNED(8); +u32 __osSiAccessQueueEnabled = 0; + +void __osSiCreateAccessQueue(void) { + __osSiAccessQueueEnabled = 1; + osCreateMesgQueue(&__osSiAccessQueue, siAccessBuf, SI_Q_BUF_LEN); + osSendMesg(&__osSiAccessQueue, NULL, OS_MESG_NOBLOCK); +} + +void __osSiGetAccess(void) { + OSMesg dummyMesg; + if (!__osSiAccessQueueEnabled) + __osSiCreateAccessQueue(); + osRecvMesg(&__osSiAccessQueue, &dummyMesg, OS_MESG_BLOCK); +} + +void __osSiRelAccess(void) { + osSendMesg(&__osSiAccessQueue, NULL, OS_MESG_NOBLOCK); +} diff --git a/lib/ultralib/src/io/sigetstat.c b/lib/ultralib/src/io/sigetstat.c new file mode 100644 index 0000000..0225445 --- /dev/null +++ b/lib/ultralib/src/io/sigetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "siint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 __osSiGetStatus() { + return IO_READ(SI_STATUS_REG); +} diff --git a/lib/ultralib/src/io/siint.h b/lib/ultralib/src/io/siint.h new file mode 100755 index 0000000..636a87f --- /dev/null +++ b/lib/ultralib/src/io/siint.h @@ -0,0 +1,15 @@ +#ifndef _SIINT_H +#define _SIINT_H + +#include "PR/os_internal.h" +#include "PR/rcp.h" + +extern s32 __osEepromRead16K; +extern u8 __osPfsInodeCacheBank; + +void __osSiGetAccess(void); +void __osSiRelAccess(void); +int __osSiDeviceBusy(void); +void __osSiCreateAccessQueue(void); + +#endif diff --git a/lib/ultralib/src/io/sirawdma.c b/lib/ultralib/src/io/sirawdma.c new file mode 100644 index 0000000..e27ff10 --- /dev/null +++ b/lib/ultralib/src/io/sirawdma.c @@ -0,0 +1,29 @@ +#include "PR/os_internal.h" +#include "siint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSiRawStartDma(s32 direction, void *dramAddr) { + if (IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY)) { + return -1; + } + + if (direction == OS_WRITE) { + osWritebackDCache(dramAddr, 64); + } + + IO_WRITE(SI_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr)); + + if (direction == OS_READ) { + IO_WRITE(SI_PIF_ADDR_RD64B_REG, PIF_RAM_START); + } else { + IO_WRITE(SI_PIF_ADDR_WR64B_REG, PIF_RAM_START); + } + + if (direction == OS_READ) { + osInvalDCache(dramAddr, 64); + } + + return 0; +} diff --git a/lib/ultralib/src/io/sirawread.c b/lib/ultralib/src/io/sirawread.c new file mode 100644 index 0000000..5381cf1 --- /dev/null +++ b/lib/ultralib/src/io/sirawread.c @@ -0,0 +1,14 @@ +#include "PR/os_internal.h" +#include "siint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSiRawReadIo(u32 devAddr, u32* data) { + if (__osSiDeviceBusy()) { + return -1; + } + + *data = IO_READ(devAddr); + return 0; +} diff --git a/lib/ultralib/src/io/sirawwrite.c b/lib/ultralib/src/io/sirawwrite.c new file mode 100644 index 0000000..9967c1d --- /dev/null +++ b/lib/ultralib/src/io/sirawwrite.c @@ -0,0 +1,14 @@ +#include "PR/os_internal.h" +#include "siint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSiRawWriteIo(u32 devAddr, u32 data) { + if (__osSiDeviceBusy()) { + return -1; + } + + IO_WRITE(devAddr, data); + return 0; +} diff --git a/lib/ultralib/src/io/sp.c b/lib/ultralib/src/io/sp.c new file mode 100755 index 0000000..95d5b20 --- /dev/null +++ b/lib/ultralib/src/io/sp.c @@ -0,0 +1,17 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "PR/sptask.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +int __osSpDeviceBusy() { + register u32 stat = IO_READ(SP_STATUS_REG); + + if (stat & (SP_STATUS_DMA_BUSY | SP_STATUS_DMA_FULL | SP_STATUS_IO_FULL)) { + return TRUE; + } + + return FALSE; +} diff --git a/lib/ultralib/src/io/spgetstat.c b/lib/ultralib/src/io/spgetstat.c new file mode 100755 index 0000000..0cdfda6 --- /dev/null +++ b/lib/ultralib/src/io/spgetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +u32 __osSpGetStatus() { + return IO_READ(SP_STATUS_REG); +} diff --git a/lib/ultralib/src/io/sprawdma.c b/lib/ultralib/src/io/sprawdma.c new file mode 100755 index 0000000..41239b1 --- /dev/null +++ b/lib/ultralib/src/io/sprawdma.c @@ -0,0 +1,30 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../os/osint.h" +#include "assert.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSpRawStartDma(s32 direction, u32 devAddr, void *dramAddr, u32 size) { + // These asserts are present in debug builds, but the line numbers won't match as-is + // TODO Add an assert spoofing macro that lets you specify a line number + assert(((u32)devAddr & 0x7) == 0); + assert(((u32)dramAddr & 0x7) == 0); + assert(((u32)size & 0x7) == 0); + + if (__osSpDeviceBusy()) { + return -1; + } + + IO_WRITE(SP_MEM_ADDR_REG, devAddr); + IO_WRITE(SP_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr)); + + if (direction == OS_READ) { + IO_WRITE(SP_WR_LEN_REG, size - 1); + } else { + IO_WRITE(SP_RD_LEN_REG, size - 1); + } + + return 0; +} diff --git a/lib/ultralib/src/io/sprawread.c b/lib/ultralib/src/io/sprawread.c new file mode 100755 index 0000000..affc78b --- /dev/null +++ b/lib/ultralib/src/io/sprawread.c @@ -0,0 +1,16 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSpRawReadIo(u32 devAddr, u32 *data) { + if (__osSpDeviceBusy()) { + return -1; + } + + *data = IO_READ(devAddr); + return 0; +} + diff --git a/lib/ultralib/src/io/sprawwrite.c b/lib/ultralib/src/io/sprawwrite.c new file mode 100755 index 0000000..f6451ae --- /dev/null +++ b/lib/ultralib/src/io/sprawwrite.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "../os/osint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSpRawWriteIo(u32 devAddr, u32 data) { + if (__osSpDeviceBusy()) { + return -1; + } + + IO_WRITE(devAddr, data); + return 0; +} diff --git a/lib/ultralib/src/io/spsetpc.c b/lib/ultralib/src/io/spsetpc.c new file mode 100644 index 0000000..dce0b5d --- /dev/null +++ b/lib/ultralib/src/io/spsetpc.c @@ -0,0 +1,15 @@ +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 __osSpSetPc(u32 pc) { + register u32 status = IO_READ(SP_STATUS_REG); + + if (!(status & SP_STATUS_HALT)) { + return -1; + } + IO_WRITE(SP_PC_REG, pc); + + return 0; +} diff --git a/lib/ultralib/src/io/spsetstat.c b/lib/ultralib/src/io/spsetstat.c new file mode 100755 index 0000000..2ab47e0 --- /dev/null +++ b/lib/ultralib/src/io/spsetstat.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void __osSpSetStatus(u32 data) { + IO_WRITE(SP_STATUS_REG, data); +} diff --git a/lib/ultralib/src/io/sptask.c b/lib/ultralib/src/io/sptask.c new file mode 100755 index 0000000..13d6f00 --- /dev/null +++ b/lib/ultralib/src/io/sptask.c @@ -0,0 +1,63 @@ +#include "PR/os_internal.h" +#include "PR/sptask.h" +#include "PR/rcp.h" +#include "../os/osint.h" + +#define _osVirtualToPhysical(ptr) \ + if (ptr != NULL) \ + { \ + ptr = (void *)osVirtualToPhysical(ptr); \ + } + +static OSTask tmp_task; + +static OSTask *_VirtualToPhysicalTask(OSTask *intp) { + OSTask *tp; + tp = &tmp_task; + bcopy(intp, tp, sizeof(OSTask)); + + _osVirtualToPhysical(tp->t.ucode); + _osVirtualToPhysical(tp->t.ucode_data); + _osVirtualToPhysical(tp->t.dram_stack); + _osVirtualToPhysical(tp->t.output_buff); + _osVirtualToPhysical(tp->t.output_buff_size); + _osVirtualToPhysical(tp->t.data_ptr); + _osVirtualToPhysical(tp->t.yield_data_ptr); + return tp; +} + +void osSpTaskLoad(OSTask *intp) { + OSTask *tp; + + tp = _VirtualToPhysicalTask(intp); + + if (tp->t.flags & OS_TASK_YIELDED) { + tp->t.ucode_data = tp->t.yield_data_ptr; + tp->t.ucode_data_size = tp->t.yield_data_size; + intp->t.flags &= ~OS_TASK_YIELDED; + if (tp->t.flags & OS_TASK_LOADABLE) + tp->t.ucode = (u64 *)IO_READ((u32)intp->t.yield_data_ptr + OS_YIELD_DATA_SIZE - 4); + } + + osWritebackDCache(tp, sizeof(OSTask)); + __osSpSetStatus(SP_CLR_YIELD | SP_CLR_YIELDED | SP_CLR_TASKDONE | SP_SET_INTR_BREAK); + + while (__osSpSetPc(SP_IMEM_START) == -1) { + } + + while (__osSpRawStartDma(1, (SP_IMEM_START - sizeof(*tp)), tp, sizeof(OSTask)) == -1) { + } + + while (__osSpDeviceBusy()) { + } + + while (__osSpRawStartDma(1, SP_IMEM_START, tp->t.ucode_boot, tp->t.ucode_boot_size) == -1) { + } +} + +void osSpTaskStartGo(OSTask *tp) { + while (__osSpDeviceBusy()) { + } + + __osSpSetStatus(SP_SET_INTR_BREAK | SP_CLR_SSTEP | SP_CLR_BROKE | SP_CLR_HALT); +} diff --git a/lib/ultralib/src/io/sptaskyield.c b/lib/ultralib/src/io/sptaskyield.c new file mode 100755 index 0000000..78bacae --- /dev/null +++ b/lib/ultralib/src/io/sptaskyield.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +void osSpTaskYield(void) { + __osSpSetStatus(SP_SET_YIELD); +} diff --git a/lib/ultralib/src/io/sptaskyielded.c b/lib/ultralib/src/io/sptaskyielded.c new file mode 100755 index 0000000..6c18c21 --- /dev/null +++ b/lib/ultralib/src/io/sptaskyielded.c @@ -0,0 +1,18 @@ +#include "PR/os_internal.h" +#include "PR/sptask.h" +#include "PR/rcp.h" + +OSYieldResult osSpTaskYielded(OSTask *tp) { + u32 status; + OSYieldResult result; + + status = __osSpGetStatus(); + result = status >> 8; + result &= 1; + + if (status & SP_STATUS_YIELD) { + tp->t.flags = ~(OS_TASK_DP_WAIT) & (tp->t.flags | result); + } + + return result; +} diff --git a/lib/ultralib/src/io/vi.c b/lib/ultralib/src/io/vi.c new file mode 100644 index 0000000..bffed92 --- /dev/null +++ b/lib/ultralib/src/io/vi.c @@ -0,0 +1,39 @@ +#include <macros.h> +#include <PR/os_internal.h> +#include <PR/R4300.h> +#include <PR/rcp.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +static __OSViContext vi[2] ALIGNED(8) = {0}; +__OSViContext *__osViCurr = &vi[0]; +__OSViContext *__osViNext = &vi[1]; + +void __osViInit(void) { + bzero(vi, sizeof(vi)); + __osViCurr = &vi[0]; + __osViNext = &vi[1]; + __osViNext->retraceCount = 1; + __osViCurr->retraceCount = 1; + __osViNext->framep = (void*)K0BASE; + __osViCurr->framep = (void*)K0BASE; + + if (osTvType == OS_TV_TYPE_PAL) { + __osViNext->modep = &osViModePalLan1; + } else if (osTvType == OS_TV_TYPE_MPAL) { + __osViNext->modep = &osViModeMpalLan1; + } else { + __osViNext->modep = &osViModeNtscLan1; + } + + __osViNext->state = VI_STATE_BLACK; + __osViNext->control = __osViNext->modep->comRegs.ctrl; + + while (IO_READ(VI_CURRENT_REG) > 10) { //wait for vsync? + } + + IO_WRITE(VI_CONTROL_REG, 0); //pixel size blank (no data, no sync) + __osViSwapContext(); +} diff --git a/lib/ultralib/src/io/viblack.c b/lib/ultralib/src/io/viblack.c new file mode 100644 index 0000000..7e8ea81 --- /dev/null +++ b/lib/ultralib/src/io/viblack.c @@ -0,0 +1,17 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViBlack(u8 active) { + register u32 saveMask = __osDisableInt(); + + if (active) { + __osViNext->state |= VI_STATE_BLACK; + } else { + __osViNext->state &= ~VI_STATE_BLACK; + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/viextendvstart.c b/lib/ultralib/src/io/viextendvstart.c new file mode 100644 index 0000000..8fa8074 --- /dev/null +++ b/lib/ultralib/src/io/viextendvstart.c @@ -0,0 +1,6 @@ +#include <PR/os_internal.h> +#include "viint.h" + +void osViExtendVStart(u32 value) { + __additional_scanline = value; +} diff --git a/lib/ultralib/src/io/vifade.c b/lib/ultralib/src/io/vifade.c new file mode 100644 index 0000000..2812860 --- /dev/null +++ b/lib/ultralib/src/io/vifade.c @@ -0,0 +1,18 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViFade(u8 active, u16 factor) { + register u32 saveMask = __osDisableInt(); + + if (active) { + __osViNext->y.offset = factor & VI_2_10_FPART_MASK; + __osViNext->state |= VI_STATE_FADE; + } else { + __osViNext->state &= ~VI_STATE_FADE; + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/vigetcurrcontext.c b/lib/ultralib/src/io/vigetcurrcontext.c new file mode 100644 index 0000000..729d902 --- /dev/null +++ b/lib/ultralib/src/io/vigetcurrcontext.c @@ -0,0 +1,9 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +__OSViContext *__osViGetCurrentContext(void) { + return __osViCurr; +} diff --git a/lib/ultralib/src/io/vigetcurrframebuf.c b/lib/ultralib/src/io/vigetcurrframebuf.c new file mode 100644 index 0000000..987e86b --- /dev/null +++ b/lib/ultralib/src/io/vigetcurrframebuf.c @@ -0,0 +1,10 @@ +#include <PR/os_internal.h> +#include "viint.h" + +void *osViGetCurrentFramebuffer(void) { + register u32 saveMask = __osDisableInt(); + void *framep = __osViCurr->framep; + + __osRestoreInt(saveMask); + return framep; +} diff --git a/lib/ultralib/src/io/vigetfield.c b/lib/ultralib/src/io/vigetfield.c new file mode 100644 index 0000000..395e912 --- /dev/null +++ b/lib/ultralib/src/io/vigetfield.c @@ -0,0 +1,6 @@ +#include <PR/os_internal.h> +#include <PR/rcp.h> + +u32 osViGetCurrentField(void) { + return IO_READ(VI_CURRENT_REG) & 1; +} diff --git a/lib/ultralib/src/io/vigetline.c b/lib/ultralib/src/io/vigetline.c new file mode 100644 index 0000000..1eed3cd --- /dev/null +++ b/lib/ultralib/src/io/vigetline.c @@ -0,0 +1,6 @@ +#include <PR/os_internal.h> +#include <PR/rcp.h> + +u32 osViGetCurrentLine(void) { + return IO_READ(VI_CURRENT_REG); +} diff --git a/lib/ultralib/src/io/vigetmode.c b/lib/ultralib/src/io/vigetmode.c new file mode 100644 index 0000000..bb3fcd0 --- /dev/null +++ b/lib/ultralib/src/io/vigetmode.c @@ -0,0 +1,10 @@ +#include <PR/os_internal.h> +#include "viint.h" + +u32 osViGetCurrentMode(void) { + register u32 savedMask = __osDisableInt(); + register u32 modeType = __osViCurr->modep->type; + + __osRestoreInt(savedMask); + return modeType; +} diff --git a/lib/ultralib/src/io/vigetnextcontext.c b/lib/ultralib/src/io/vigetnextcontext.c new file mode 100644 index 0000000..5692890 --- /dev/null +++ b/lib/ultralib/src/io/vigetnextcontext.c @@ -0,0 +1,6 @@ +#include <PR/os_internal.h> +#include "viint.h" + +__OSViContext *__osViGetNextContext(void) { + return __osViNext; +} diff --git a/lib/ultralib/src/io/vigetnextframebuf.c b/lib/ultralib/src/io/vigetnextframebuf.c new file mode 100644 index 0000000..9158281 --- /dev/null +++ b/lib/ultralib/src/io/vigetnextframebuf.c @@ -0,0 +1,10 @@ +#include <PR/os_internal.h> +#include "viint.h" + +void *osViGetNextFramebuffer(void) { + register u32 saveMask = __osDisableInt(); + void *framep = __osViNext->framep; + + __osRestoreInt(saveMask); + return framep; +} diff --git a/lib/ultralib/src/io/vigetstat.c b/lib/ultralib/src/io/vigetstat.c new file mode 100644 index 0000000..eea94a7 --- /dev/null +++ b/lib/ultralib/src/io/vigetstat.c @@ -0,0 +1,6 @@ +#include <PR/os_internal.h> +#include <PR/rcp.h> + +u32 osViGetStatus(void) { + return IO_READ(VI_STATUS_REG); +} diff --git a/lib/ultralib/src/io/viint.h b/lib/ultralib/src/io/viint.h new file mode 100644 index 0000000..3ae94c8 --- /dev/null +++ b/lib/ultralib/src/io/viint.h @@ -0,0 +1,70 @@ +#ifndef _VIINT_H +#define _VIINT_H +#include "PR/os_internal.h" + +#define OS_TV_TYPE_PAL 0 +#define OS_TV_TYPE_NTSC 1 +#define OS_TV_TYPE_MPAL 2 + +#define VI_STATE_MODE_UPDATED 0x01 +#define VI_STATE_XSCALE_UPDATED 0x02 +#define VI_STATE_YSCALE_UPDATED 0x04 +#define VI_STATE_CTRL_UPDATED 0x08 // related to control regs changing +#define VI_STATE_BUFFER_UPDATED 0x10 // swap buffer +#define VI_STATE_BLACK 0x20 // probably related to a black screen +#define VI_STATE_REPEATLINE 0x40 // repeat line? +#define VI_STATE_FADE 0x80 // fade + +#define VI_CTRL_ANTIALIAS_MODE_3 0x00300 /* Bit [9:8] anti-alias mode */ +#define VI_CTRL_ANTIALIAS_MODE_2 0x00200 /* Bit [9:8] anti-alias mode */ +#define VI_CTRL_ANTIALIAS_MODE_1 0x00100 /* Bit [9:8] anti-alias mode */ + +#define VI_SCALE_MASK 0xfff //see rcp scale_x/scale_y +#define VI_2_10_FPART_MASK 0x3ff +#define VI_SUBPIXEL_SH 0x10 + +#define BURST(hsync_width, color_width, vsync_width, color_start) \ + (hsync_width | (color_width << 8) | (vsync_width << 16) | (color_start << 20)) +#define WIDTH(v) v +#define VSYNC(v) v +#define HSYNC(duration, leap) (duration | (leap << 16)) +#define LEAP(upper, lower) ((upper << 16) | lower) +#define START(start, end) ((start << 16) | end) + +#define FTOFIX(val, i, f) ((u32)(val * (f32)(1 << f)) & ((1 << (i + f)) - 1)) + +#define F210(val) FTOFIX(val, 2, 10) +#define SCALE(scaleup, off) (F210((1.0f / (f32)scaleup)) | (F210((f32)off) << 16)) + +#define VCURRENT(v) v //seemingly unused +#define ORIGIN(v) v +#define VINTR(v) v +#define HSTART START + +typedef struct +{ + /* 0x0 */ f32 factor; + /* 0x4 */ u16 offset; + /* 0x8 */ u32 scale; +} __OSViScale; + +typedef struct +{ + /* 0x0 */ u16 state; + /* 0x2 */ u16 retraceCount; + /* 0x4 */ void *framep; + /* 0x8 */ OSViMode *modep; + /* 0xC */ u32 control; + /* 0x10 */ OSMesgQueue *msgq; + /* 0x14 */ OSMesg msg; + /* 0x18 */ __OSViScale x; + /* 0x24 */ __OSViScale y; +} __OSViContext; // 0x30 bytes + +void __osViSwapContext(void); +extern __OSViContext *__osViCurr; +extern __OSViContext *__osViNext; +extern u32 __additional_scanline; +__OSViContext *__osViGetCurrentContext(void); +void __osViInit(void); +#endif diff --git a/lib/ultralib/src/io/vimgr.c b/lib/ultralib/src/io/vimgr.c new file mode 100644 index 0000000..d4766b5 --- /dev/null +++ b/lib/ultralib/src/io/vimgr.c @@ -0,0 +1,110 @@ +#include <macros.h> +#include <PR/os_internal.h> +#include <PR/rcp.h> +#include "viint.h" +#include "../os/osint.h" + +OSDevMgr __osViDevMgr = {0}; +u32 __additional_scanline = 0; +static OSThread viThread; +static unsigned char viThreadStack[OS_VIM_STACKSIZE] ALIGNED(16); +static OSMesgQueue viEventQueue; +static OSMesg viEventBuf[5] ALIGNED(8); +static OSIoMesg viRetraceMsg ALIGNED(8); +static OSIoMesg viCounterMsg ALIGNED(8); + +static void viMgrMain(void *arg); +void osCreateViManager(OSPri pri) +{ + u32 savedMask; + OSPri myPri; + OSPri oldPri; + + if (!__osViDevMgr.active) { + __osTimerServicesInit(); + __additional_scanline = 0; + osCreateMesgQueue(&viEventQueue, viEventBuf, ARRLEN(viEventBuf)); + viRetraceMsg.hdr.type = OS_MESG_TYPE_VRETRACE; + viRetraceMsg.hdr.pri = OS_MESG_PRI_NORMAL; + viRetraceMsg.hdr.retQueue = NULL; + viCounterMsg.hdr.type = OS_MESG_TYPE_COUNTER; + viCounterMsg.hdr.pri = OS_MESG_PRI_NORMAL; + viCounterMsg.hdr.retQueue = NULL; + osSetEventMesg(OS_EVENT_VI, &viEventQueue, &viRetraceMsg); + osSetEventMesg(OS_EVENT_COUNTER, &viEventQueue, &viCounterMsg); + oldPri = -1; + myPri = osGetThreadPri(NULL); + + if (myPri < pri) { + oldPri = myPri; + osSetThreadPri(NULL, pri); + } + + savedMask = __osDisableInt(); + __osViDevMgr.active = TRUE; + __osViDevMgr.thread = &viThread; + __osViDevMgr.cmdQueue = &viEventQueue; + __osViDevMgr.evtQueue = &viEventQueue; + __osViDevMgr.acsQueue = NULL; + __osViDevMgr.dma = NULL; + __osViDevMgr.edma = NULL; + osCreateThread(&viThread, 0, viMgrMain, &__osViDevMgr, &viThreadStack[OS_VIM_STACKSIZE], pri); + __osViInit(); + osStartThread(&viThread); + __osRestoreInt(savedMask); + + if (oldPri != -1) { + osSetThreadPri(0, oldPri); + } + } +} + +static void viMgrMain(void *arg) { + __OSViContext *vc; + OSDevMgr *dm; + OSIoMesg *mb; + static u16 retrace; + s32 first; + u32 count; + + mb = NULL; + first = 0; + vc = __osViGetCurrentContext(); + retrace = vc->retraceCount; + if (retrace == 0) + retrace = 1; + dm = (OSDevMgr *)arg; + + while (TRUE) { + osRecvMesg(dm->evtQueue, (OSMesg)&mb, OS_MESG_BLOCK); + switch (mb->hdr.type) { + case OS_MESG_TYPE_VRETRACE: + __osViSwapContext(); + retrace--; + + if (retrace == 0) { + vc = __osViGetCurrentContext(); + if (vc->msgq != NULL) + osSendMesg(vc->msgq, vc->msg, OS_MESG_NOBLOCK); + retrace = vc->retraceCount; + } + + __osViIntrCount++; + + if (first) { + count = osGetCount(); + __osCurrentTime = count; + first = 0; + } + + count = __osBaseCounter; + __osBaseCounter = osGetCount(); + count = __osBaseCounter - count; + __osCurrentTime = __osCurrentTime + count; + break; + case OS_MESG_TYPE_COUNTER: + __osTimerInterrupt(); + break; + } + } +} diff --git a/lib/ultralib/src/io/virepeatline.c b/lib/ultralib/src/io/virepeatline.c new file mode 100644 index 0000000..905538e --- /dev/null +++ b/lib/ultralib/src/io/virepeatline.c @@ -0,0 +1,17 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViRepeatLine(u8 active) { + register u32 saveMask = __osDisableInt(); + + if (active) { + __osViNext->state |= VI_STATE_REPEATLINE; + } else { + __osViNext->state &= ~VI_STATE_REPEATLINE; + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/visetevent.c b/lib/ultralib/src/io/visetevent.c new file mode 100644 index 0000000..589647a --- /dev/null +++ b/lib/ultralib/src/io/visetevent.c @@ -0,0 +1,14 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSetEvent(OSMesgQueue *mq, OSMesg m, u32 retraceCount) { + register u32 saveMask = __osDisableInt(); + + __osViNext->msgq = mq; + __osViNext->msg = m; + __osViNext->retraceCount = retraceCount; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/visetmode.c b/lib/ultralib/src/io/visetmode.c new file mode 100644 index 0000000..655cba6 --- /dev/null +++ b/lib/ultralib/src/io/visetmode.c @@ -0,0 +1,14 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSetMode(OSViMode *modep) { + register u32 saveMask = __osDisableInt(); + + __osViNext->modep = modep; + __osViNext->state = VI_STATE_MODE_UPDATED; + __osViNext->control = __osViNext->modep->comRegs.ctrl; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/visetspecial.c b/lib/ultralib/src/io/visetspecial.c new file mode 100644 index 0000000..e8f90b8 --- /dev/null +++ b/lib/ultralib/src/io/visetspecial.c @@ -0,0 +1,48 @@ +#include <PR/os_internal.h> +#include <PR/rcp.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSetSpecialFeatures(u32 func) { + register u32 saveMask = __osDisableInt(); + + if ((func & OS_VI_GAMMA_ON) != 0) { + __osViNext->control |= VI_CTRL_GAMMA_ON; + } + + if ((func & OS_VI_GAMMA_OFF) != 0) { + __osViNext->control &= ~VI_CTRL_GAMMA_ON; + } + + if ((func & OS_VI_GAMMA_DITHER_ON) != 0) { + __osViNext->control |= VI_CTRL_GAMMA_DITHER_ON; + } + + if ((func & OS_VI_GAMMA_DITHER_OFF) != 0) { + __osViNext->control &= ~VI_CTRL_GAMMA_DITHER_ON; + } + + if ((func & OS_VI_DIVOT_ON) != 0) { + __osViNext->control |= VI_CTRL_DIVOT_ON; + } + + if ((func & OS_VI_DIVOT_OFF) != 0) { + __osViNext->control &= ~VI_CTRL_DIVOT_ON; + } + + if ((func & OS_VI_DITHER_FILTER_ON) != 0) { + __osViNext->control |= VI_CTRL_DITHER_FILTER_ON; + __osViNext->control &= ~VI_CTRL_ANTIALIAS_MASK; + } + + if ((func & OS_VI_DITHER_FILTER_OFF) != 0) { + __osViNext->control &= ~VI_CTRL_DITHER_FILTER_ON; + __osViNext->control |= __osViNext->modep->comRegs.ctrl & VI_CTRL_ANTIALIAS_MASK; + } + + __osViNext->state |= VI_STATE_CTRL_UPDATED; + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/visetxscale.c b/lib/ultralib/src/io/visetxscale.c new file mode 100644 index 0000000..328987c --- /dev/null +++ b/lib/ultralib/src/io/visetxscale.c @@ -0,0 +1,16 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSetXScale(f32 value) { + register u32 nomValue; + register u32 saveMask = __osDisableInt(); + + __osViNext->x.factor = value; + __osViNext->state |= VI_STATE_XSCALE_UPDATED; + nomValue = __osViNext->modep->comRegs.xScale & VI_SCALE_MASK; + __osViNext->x.scale = (u32)(__osViNext->x.factor * nomValue) & VI_SCALE_MASK; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/visetyscale.c b/lib/ultralib/src/io/visetyscale.c new file mode 100644 index 0000000..525e0eb --- /dev/null +++ b/lib/ultralib/src/io/visetyscale.c @@ -0,0 +1,13 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSetYScale(f32 value) { + register u32 saveMask = __osDisableInt(); + + __osViNext->y.factor = value; + __osViNext->state |= VI_STATE_YSCALE_UPDATED; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/viswapbuf.c b/lib/ultralib/src/io/viswapbuf.c new file mode 100644 index 0000000..327ed60 --- /dev/null +++ b/lib/ultralib/src/io/viswapbuf.c @@ -0,0 +1,13 @@ +#include <PR/os_internal.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osViSwapBuffer(void* frameBufPtr) { + u32 saveMask = __osDisableInt(); + + __osViNext->framep = frameBufPtr; + __osViNext->state |= VI_STATE_BUFFER_UPDATED; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/io/viswapcontext.c b/lib/ultralib/src/io/viswapcontext.c new file mode 100644 index 0000000..3095d51 --- /dev/null +++ b/lib/ultralib/src/io/viswapcontext.c @@ -0,0 +1,72 @@ +#include <PR/os_internal.h> +#include <PR/rcp.h> +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void __osViSwapContext() { + register OSViMode *vm; + register __OSViContext *vc; + u32 origin; + u32 vStart; + u32 hStart; + u32 nomValue; + u32 field; + + field = 0; + vc = __osViNext; + vm = vc->modep; + + field = IO_READ(VI_CURRENT_REG) & 1; //field num + + origin = osVirtualToPhysical(vc->framep) + (vm->fldRegs[field].origin); + if (vc->state & VI_STATE_XSCALE_UPDATED) { + vc->x.scale |= (vm->comRegs.xScale & ~VI_SCALE_MASK); + } else { + vc->x.scale = vm->comRegs.xScale; + } + + if (vc->state & VI_STATE_YSCALE_UPDATED) { + nomValue = vm->fldRegs[field].yScale & VI_SCALE_MASK; + vc->y.scale = vc->y.factor * nomValue; + vc->y.scale |= vm->fldRegs[field].yScale & ~VI_SCALE_MASK; + } else { + vc->y.scale = vm->fldRegs[field].yScale; + } + + vStart = (vm->fldRegs[field].vStart - (__additional_scanline << 0x10)) + __additional_scanline; + hStart = vm->comRegs.hStart; + + if (vc->state & VI_STATE_BLACK) { + hStart = 0; + } + + if (vc->state & VI_STATE_REPEATLINE) { + vc->y.scale = 0; + origin = osVirtualToPhysical(vc->framep); + } + + if (vc->state & VI_STATE_FADE) { + vc->y.scale = (vc->y.offset << VI_SUBPIXEL_SH) & (VI_2_10_FPART_MASK << VI_SUBPIXEL_SH); + origin = osVirtualToPhysical(vc->framep); + } + + IO_WRITE(VI_ORIGIN_REG, origin); + IO_WRITE(VI_WIDTH_REG, vm->comRegs.width); + IO_WRITE(VI_BURST_REG, vm->comRegs.burst); + IO_WRITE(VI_V_SYNC_REG, vm->comRegs.vSync); + IO_WRITE(VI_H_SYNC_REG, vm->comRegs.hSync); + IO_WRITE(VI_LEAP_REG, vm->comRegs.leap); + IO_WRITE(VI_H_START_REG, hStart); + IO_WRITE(VI_V_START_REG, vStart); + IO_WRITE(VI_V_BURST_REG, vm->fldRegs[field].vBurst); + IO_WRITE(VI_INTR_REG, vm->fldRegs[field].vIntr); + IO_WRITE(VI_X_SCALE_REG, vc->x.scale); + IO_WRITE(VI_Y_SCALE_REG, vc->y.scale); + IO_WRITE(VI_CONTROL_REG, vc->control); + + __osViNext = __osViCurr; + __osViCurr = vc; + *__osViNext = *__osViCurr; +} diff --git a/lib/ultralib/src/io/vitbl.c b/lib/ultralib/src/io/vitbl.c new file mode 100644 index 0000000..89e57e7 --- /dev/null +++ b/lib/ultralib/src/io/vitbl.c @@ -0,0 +1,1742 @@ +#include <PR/os.h> +#include <PR/rcp.h> +#include "../io/viint.h" + +OSViMode osViModeTable[56] = { + { + OS_VI_NTSC_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_NTSC_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_PAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { //[0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { //[1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_MPAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + }, + { + OS_VI_FPAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } + } +}; diff --git a/lib/ultralib/src/libc/bcmp.s b/lib/ultralib/src/libc/bcmp.s new file mode 100644 index 0000000..f6fcc8b --- /dev/null +++ b/lib/ultralib/src/libc/bcmp.s @@ -0,0 +1,92 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +WEAK(_bcmp, bcmp) +LEAF(bcmp) + xor v0, a0, a1 + blt a2, 16, bytecmp + + andi v0, v0, 0x3 + negu t8, a0 + bnez v0, unalgncmp + + andi t8, t8, 0x3 + subu a2, a2, t8 + beqz t8, wordcmp + + move v0, v1 + lwl v0, 0(a0) + lwl v1, 0(a1) + addu a0, a0, t8 + addu a1, a1, t8 + bne v0, v1, cmpne + +wordcmp: + and a3, a2, ~3 + subu a2, a2, a3 + beqz a3, bytecmp + + addu a3, a3, a0 +1: + lw v0, 0(a0) + lw v1, 0(a1) + addiu a0, a0, 4 + addiu a1, a1, 4 + bne v0, v1, cmpne + bne a0, a3, 1b + + b bytecmp +unalgncmp: + negu a3, a1 + andi a3, a3, 0x3 + subu a2, a2, a3 + beqz a3, partaligncmp + + addu a3, a3, a0 + +1: + lbu v0, 0(a0) + lbu v1, 0(a1) + addiu a0, a0, 1 + addiu a1, a1, 1 + bne v0, v1, cmpne + bne a0, a3, 1b + +partaligncmp: + and a3, a2, ~3 + subu a2, a2, a3 + beqz a3, bytecmp + + addu a3, a3, a0 + +1: + lwl v0, 0(a0) + lwr v0, 3(a0) + lw v1, 0(a1) + addiu a0, a0, 4 + addiu a1, a1, 4 + bne v0, v1, cmpne + bne a0, a3, 1b + +bytecmp: + addu a3, a2, a0 + blez a2, cmpdone + +1: + lbu v0, 0(a0) + lbu v1, 0(a1) + addiu a0, a0, 1 + addiu a1, a1, 1 + bne v0, v1, cmpne + bne a0, a3, 1b + +cmpdone: + move v0, zero + jr ra +cmpne: + li v0, 1 + jr ra + +END(bcmp) diff --git a/lib/ultralib/src/libc/bcopy.s b/lib/ultralib/src/libc/bcopy.s new file mode 100644 index 0000000..9bf1583 --- /dev/null +++ b/lib/ultralib/src/libc/bcopy.s @@ -0,0 +1,218 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +WEAK(_bcopy, bcopy) +LEAF(bcopy) + move a3, a1 + beqz a2, ret + beq a0, a1, ret + blt a1, a0, goforwards + + add v0, a0, a2 + bge a1, v0, goforwards + b gobackwards + +goforwards: + + blt a2, 16, forwards_bytecopy + + andi v0, a0, 0x3 + andi v1, a1, 0x3 + beq v0, v1,forwalignable + + +forwards_bytecopy: + beqz a2, ret + addu v1, a0, a2 +99: + lb v0, 0(a0) + addiu a0, a0, 1 + sb v0, 0(a1) + addiu a1, a1, 1 + bne a0, v1, 99b +ret: + move v0, a3 + jr ra + +forwalignable: + beqz v0, forwards + beq v0, 1, forw_copy3 + beq v0, 2, forw_copy2 + + lb v0, 0(a0) + addiu a0, a0, 1 + sb v0, 0(a1) + addiu a1, a1, 1 + addiu a2, a2, -1 + b forwards + +forw_copy2: + lh v0, 0(a0) + addiu a0, a0, 2 + sh v0, 0(a1) + addiu a1, a1, 2 + addiu a2, a2, -2 + b forwards + +forw_copy3: + lb v0, 0(a0) + lh v1, 1(a0) + addiu a0, a0, 3 + sb v0, 0(a1) + sh v1, 1(a1) + addiu a1, a1, 3 + addiu a2, a2, -3 + +forwards: +forwards_32: + blt a2, 32, forwards_16 + lw v0, 0(a0) + lw v1, 4(a0) + lw t0, 8(a0) + lw t1, 12(a0) + lw t2, 16(a0) + lw t3, 20(a0) + lw ta0, 24(a0) + lw ta1, 28(a0) + addiu a0, a0, 32 + sw v0, 0(a1) + sw v1, 4(a1) + sw t0, 8(a1) + sw t1, 12(a1) + sw t2, 16(a1) + sw t3, 20(a1) + sw ta0, 24(a1) + sw ta1, 28(a1) + addiu a1, a1, 32 + addiu a2, a2, -32 + b forwards_32 + +forwards_16: + blt a2, 16, forwards_4 + lw v0, 0(a0) + lw v1, 4(a0) + lw t0, 8(a0) + lw t1, 12(a0) + addiu a0, a0, 16 + sw v0, 0(a1) + sw v1, 4(a1) + sw t0, 8(a1) + sw t1, 12(a1) + addiu a1, a1, 16 + addiu a2, a2, -16 + b forwards_16 + +forwards_4: + blt a2, 4, forwards_bytecopy + + lw v0, 0(a0) + addiu a0, a0, 4 + sw v0, 0(a1) + addiu a1, a1, 4 + addiu a2, a2, -4 + b forwards_4 + +gobackwards: + add a0, a0,a2 + add a1, a1,a2 + blt a2, 16, backwards_bytecopy + + andi v0, a0, 0x3 + andi v1, a1, 0x3 + beq v0, v1,backalignable + +backwards_bytecopy: + beqz a2, ret + addiu a0, a0, -1 + addiu a1, a1, -1 + subu v1, a0,a2 +99: + lb v0, 0(a0) + addiu a0, a0, -1 + sb v0, 0(a1) + addiu a1, a1, -1 + bne a0, v1,99b + + move v0, a3 + jr ra +backalignable: + beqz v0, backwards + beq v0, 3, back_copy3 + beq v0, 2, back_copy2 + lb v0, -1(a0) + addiu a0, a0, -1 + sb v0, -1(a1) + addiu a1, a1, -1 + addiu a2, a2, -1 + b backwards + +back_copy2: + lh v0, -2(a0) + addiu a0, a0, -2 + sh v0, -2(a1) + addiu a1, a1, -2 + addiu a2, a2, -2 + b backwards + +back_copy3: + lb v0, -1(a0) + lh v1, -3(a0) + addiu a0, a0, -3 + sb v0, -1(a1) + sh v1, -3(a1) + addiu a1, a1, -3 + addiu a2, a2, -3 + +backwards: +backwards_32: + blt a2, 32, backwards_16 + lw v0, -4(a0) + lw v1, -8(a0) + lw t0, -12(a0) + lw t1, -16(a0) + lw t2, -20(a0) + lw t3, -24(a0) + lw ta0, -28(a0) + lw ta1, -32(a0) + addiu a0, a0, -32 + sw v0, -4(a1) + sw v1, -8(a1) + sw t0, -12(a1) + sw t1, -16(a1) + sw t2, -20(a1) + sw t3, -24(a1) + sw ta0, -28(a1) + sw ta1, -32(a1) + addiu a1, a1, -32 + addiu a2, a2, -32 + b backwards_32 + +backwards_16: + blt a2, 16, backwards_4 + lw v0, -4(a0) + lw v1, -8(a0) + lw t0, -12(a0) + lw t1, -16(a0) + addiu a0, a0, -16 + sw v0, -4(a1) + sw v1, -8(a1) + sw t0, -12(a1) + sw t1, -16(a1) + addiu a1, a1, -16 + addiu a2, a2, -16 + b backwards_16 + +backwards_4: + blt a2, 4, backwards_bytecopy + lw v0, -4(a0) + addiu a0, a0, -4 + sw v0, -4(a1) + addiu a1, a1, -4 + addiu a2, a2, -4 + b backwards_4 + +END(bcopy) +/* +*/ diff --git a/lib/ultralib/src/libc/bzero.s b/lib/ultralib/src/libc/bzero.s new file mode 100644 index 0000000..13dcfa2 --- /dev/null +++ b/lib/ultralib/src/libc/bzero.s @@ -0,0 +1,58 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +WEAK(_bzero, bzero) +WEAK(_blkclr, blkclr) +LEAF(bzero) +XLEAF(blkclr) + negu v1, a0 + blt a1, 12, bytezero + + andi v1, v1, 0x3 + subu a1, a1, v1 + + beqz v1, blkzero + swl zero, 0(a0) + addu a0, a0, v1 +blkzero: + and a3, a1, ~31 + subu a1, a1, a3 + beqz a3, wordzero + + addu a3, a3, a0 +1: + sw zero, 0(a0) + sw zero, 4(a0) + sw zero, 8(a0) + sw zero, 12(a0) + addiu a0, a0, 32 + sw zero, -16(a0) + sw zero, -12(a0) + sw zero, -8(a0) + sw zero, -4(a0) + bne a0, a3, 1b + +wordzero: + and a3, a1, ~3 + subu a1, a1, a3 + beqz a3, bytezero + + addu a3, a3, a0 +1: + addiu a0, a0, 4 + sw zero, -4(a0) + bne a0, a3, 1b + +bytezero: + blez a1, zerodone + #nop + addu a1, a1, a0 +1: + addiu a0, a0, 1 + sb zero, -1(a0) + bne a0, a1, 1b +zerodone: + jr ra +END(bzero) diff --git a/lib/ultralib/src/libc/ldiv.c b/lib/ultralib/src/libc/ldiv.c new file mode 100755 index 0000000..59644e9 --- /dev/null +++ b/lib/ultralib/src/libc/ldiv.c @@ -0,0 +1,33 @@ +#include "stdlib.h" + +// TODO: these come from headers +#ident "$Revision: 1.34 $" +#ident "$Revision: 1.5 $" + +ldiv_t ldiv(long num, long denom) { + ldiv_t ret; + + ret.quot = num / denom; + ret.rem = num - denom * ret.quot; + + if (ret.quot < 0 && ret.rem > 0) { + ret.quot++; + ret.rem -= denom; + } + + return ret; +} + +lldiv_t lldiv(long long num, long long denom) { + lldiv_t ret; + + ret.quot = num / denom; + ret.rem = num - denom * ret.quot; + + if (ret.quot < 0 && ret.rem > 0) { + ret.quot++; + ret.rem -= denom; + } + + return ret; +} diff --git a/lib/ultralib/src/libc/ll.c b/lib/ultralib/src/libc/ll.c new file mode 100755 index 0000000..71582bf --- /dev/null +++ b/lib/ultralib/src/libc/ll.c @@ -0,0 +1,46 @@ +unsigned long long __ull_rshift(unsigned long long a0, unsigned long long a1) { + return a0 >> a1; +} + +unsigned long long __ull_rem(unsigned long long a0, unsigned long long a1) { + return a0 % a1; +} + +unsigned long long __ull_div(unsigned long long a0, unsigned long long a1) { + return a0 / a1; +} + +unsigned long long __ll_lshift(unsigned long long a0, unsigned long long a1) { + return a0 << a1; +} + +long long __ll_rem(unsigned long long a0, long long a1) { + return a0 % a1; +} + +long long __ll_div(long long a0, long long a1) { + return a0 / a1; +} + +unsigned long long __ll_mul(unsigned long long a0, unsigned long long a1) { + return a0 * a1; +} + +void __ull_divremi(unsigned long long *div, unsigned long long *rem, unsigned long long a2, unsigned short a3) { + *div = a2 / a3; + *rem = a2 % a3; +} + +long long __ll_mod(long long a0, long long a1) { + long long tmp = a0 % a1; + + if ((tmp < 0 && a1 > 0) || (tmp > 0 && a1 < 0)) { + tmp += a1; + } + + return tmp; +} + +long long __ll_rshift(long long a0, long long a1) { + return a0 >> a1; +} diff --git a/lib/ultralib/src/libc/llbit.c b/lib/ultralib/src/libc/llbit.c new file mode 100755 index 0000000..73d6056 --- /dev/null +++ b/lib/ultralib/src/libc/llbit.c @@ -0,0 +1,50 @@ +#include "PR/ultratypes.h" + +s64 __ll_bit_extract(u64 *addr, unsigned int start_bit, unsigned int length) { + unsigned int words; + unsigned int lbits; + unsigned int rbits; + u64 mask; + + words = start_bit >> 6; + lbits = start_bit & ((1 << 6) - 1); + rbits = 64 - (lbits + length); + addr += words; + mask = ((u64)1 << length) - 1; + mask = mask << rbits; + return (s64)((*addr & mask) >> rbits); +} + +u64 __ull_bit_extract(u64 *addr, unsigned int start_bit, unsigned int length) { + unsigned int words; + unsigned int lbits; + unsigned int rbits; + u64 mask; + + words = start_bit >> 6; + lbits = start_bit & ((1 << 6) - 1); + rbits = 64 - (lbits + length); + addr += words; + mask = ((u64)1 << length) - 1; + mask = mask << rbits; + return (u64)((*addr & mask) >> rbits); +} + +u64 __ll_bit_insert(u64 *addr, unsigned int start_bit, unsigned int length, u64 val) { + unsigned int words; + unsigned int lbits; + unsigned int rbits; + unsigned long long llval; + unsigned long long mask; + + words = start_bit >> 6; + lbits = start_bit & 0x3f; + rbits = 64 - (lbits + length); + addr += words; + mask = ((u64)1 << length) - 1; + mask <<= rbits; + llval = (val << (64 - length)) >> lbits; + *addr = (*addr & ~mask) | llval; + llval = llval >> rbits; + return llval; +} diff --git a/lib/ultralib/src/libc/llcvt.c b/lib/ultralib/src/libc/llcvt.c new file mode 100755 index 0000000..2c423dd --- /dev/null +++ b/lib/ultralib/src/libc/llcvt.c @@ -0,0 +1,31 @@ +long long __d_to_ll(double d) { + return d; +} + +long long __f_to_ll(float f) { + return f; +} + +unsigned long long __d_to_ull(double d) { + return d; +} + +unsigned long long __f_to_ull(float f) { + return f; +} + +double __ll_to_d(long long s) { + return s; +} + +float __ll_to_f(long long s) { + return s; +} + +double __ull_to_d(unsigned long long u) { + return u; +} + +float __ull_to_f(unsigned long long u) { + return u; +} diff --git a/lib/ultralib/src/libc/sprintf.c b/lib/ultralib/src/libc/sprintf.c new file mode 100755 index 0000000..8d619f5 --- /dev/null +++ b/lib/ultralib/src/libc/sprintf.c @@ -0,0 +1,24 @@ +#include "xstdio.h" +#include "string.h" + +// TODO: this comes from a header +#ident "$Revision: 1.23 $" + +static char *proutSprintf(char *dst, const char *src, size_t count); + +int sprintf(char *dst, const char *fmt, ...) +{ + s32 ans; + va_list ap; + va_start(ap, fmt); + ans = _Printf(proutSprintf, dst, fmt, ap); + if (ans >= 0) + { + dst[ans] = 0; + } + return ans; +} +static char *proutSprintf(char *dst, const char *src, size_t count) +{ + return (char *)memcpy((u8 *)dst, (u8 *)src, count) + count; +} diff --git a/lib/ultralib/src/libc/string.c b/lib/ultralib/src/libc/string.c new file mode 100755 index 0000000..c9a2b97 --- /dev/null +++ b/lib/ultralib/src/libc/string.c @@ -0,0 +1,34 @@ +#include "PR/ultratypes.h" +#include "string.h" + +// TODO: this comes from a header +#ident "$Revision: 1.23 $" + +char *strchr(const char *s, int c) { + const char ch = c; + while (*s != ch) + { + if (*s == 0) + return NULL; + s++; + } + return (char *)s; +} + +size_t strlen(const char *s) { + const char *sc = s; + while (*sc) + sc++; + return sc - s; +} + +void *memcpy(void *s1, const void *s2, size_t n) { + char *su1 = (char *)s1; + const char *su2 = (const char *)s2; + while (n > 0) + { + *su1++ = *su2++; + n--; + } + return (void *)s1; +} diff --git a/lib/ultralib/src/libc/syncprintf.c b/lib/ultralib/src/libc/syncprintf.c new file mode 100755 index 0000000..f2e758c --- /dev/null +++ b/lib/ultralib/src/libc/syncprintf.c @@ -0,0 +1,17 @@ +#include "stdarg.h" +#include "PR/os.h" + +void __osSyncVPrintf(const char *fmt, va_list args) { + // these functions intentionally left blank. ifdeffed out in rom release +} + +void osSyncPrintf(const char *fmt, ...) { + int ans; + va_list ap; + // these functions intentionally left blank. ifdeffed out in rom release +} + +void rmonPrintf(const char *fmt, ...) { + int ans; + va_list ap; +} diff --git a/lib/ultralib/src/libc/xldtob.c b/lib/ultralib/src/libc/xldtob.c new file mode 100644 index 0000000..b032e57 --- /dev/null +++ b/lib/ultralib/src/libc/xldtob.c @@ -0,0 +1,311 @@ +#include "stdlib.h" +#include "string.h" +#include "xstdio.h" + +// TODO: these come from headers +#ident "$Revision: 1.23 $" +#ident "$Revision: 1.34 $" +#ident "$Revision: 1.5 $" + +#define BUFF_LEN 0x20 + +static s16 _Ldunscale(s16* pex, _Pft* px); +static void _Genld(_Pft* px, char code, u8* p, s16 nsig, s16 xexp); + +static const double pows[] = {10e0L, 10e1L, 10e3L, 10e7L, 10e15L, 10e31L, 10e63L, 10e127L, 10e255L}; + +// float properties +#define _D0 0 +#define _DBIAS 0x3ff +#define _DLONG 1 +#define _DOFF 4 +#define _FBIAS 0x7e +#define _FOFF 7 +#define _FRND 1 +#define _LBIAS 0x3ffe +#define _LOFF 15 +// integer properties +#define _C2 1 +#define _CSIGN 1 +#define _ILONG 0 +#define _MBMAX 8 +#define NAN 2 +#define INF 1 +#define FINITE -1 +#define _DFRAC ((1 << _DOFF) - 1) +#define _DMASK (0x7fff & ~_DFRAC) +#define _DMAX ((1 << (15 - _DOFF)) - 1) +#define _DNAN (0x8000 | _DMAX << _DOFF | 1 << (_DOFF - 1)) +#define _DSIGN 0x8000 +#define _D1 1 // big-endian order +#define _D2 2 +#define _D3 3 + +#define ALIGN(s, align) (((u32)(s) + ((align)-1)) & ~((align)-1)) + +void _Ldtob(_Pft* px, char code) { + char buff[BUFF_LEN]; + char *p; + f64 ldval; + s16 err; + s16 nsig; + s16 xexp; + + // char unused[0x4]; + p = buff; + ldval = px->v.ld; + + if (px->prec < 0) { + px->prec = 6; + } else if (px->prec == 0 && (code == 'g' || code == 'G')) { + px->prec = 1; + } + + err = _Ldunscale(&xexp, px); + if (err > 0) { + memcpy(px->s, err == 2 ? "NaN" : "Inf", px->n1 = 3); + return; + } else if (err == 0) { + nsig = 0; + xexp = 0; + } else { + int i; + int n; + + if (ldval < 0) { + ldval = -ldval; + } + + // what + if ((xexp = xexp * 30103 / 100000 - 4) < 0) { + n = ALIGN(-xexp, 4), xexp = -n; + + for (i = 0; n > 0; n >>= 1, i++) { + if (n & 1) { + ldval *= pows[i]; + } + } + } else if (xexp > 0) { + f64 factor = 1; + + xexp &= ~3; + + for (n = xexp, i = 0; n > 0; n >>= 1, i++) { + if (n & 1) { + factor *= pows[i]; + } + } + + ldval /= factor; + } + { + int gen = px->prec + ((code == 'f') ? 10 + xexp : 6); + + if (gen > 0x13) { + gen = 0x13; + } + + for (*p++ = '0'; gen > 0 && 0 < ldval; p += 8) { + int j; + int lo = ldval; + + if ((gen -= 8) > 0) { + ldval = (ldval - lo) * 1e8; + } + + for (p += 8, j = 8; lo > 0 && --j >= 0;) { + ldiv_t qr = ldiv(lo, 10); + *--p = qr.rem + '0', lo = qr.quot; + } + + while (--j >= 0) { + *--p = '0'; + } + } + + gen = p - &buff[1]; + + for (p = &buff[1], xexp += 7; *p == '0'; p++) { + --gen, --xexp; + } + + nsig = px->prec + ((code == 'f') ? xexp + 1 : ((code == 'e' || code == 'E') ? 1 : 0)); + + if (gen < nsig) { + nsig = gen; + } + + if (nsig > 0) { + char drop = nsig < gen && '5' <= p[nsig] ? '9' : '0'; + int n; + + for (n = nsig; p[--n] == drop;) { + --nsig; + } + + if (drop == '9') { + ++p[n]; + } + + if (n < 0) { + --p, ++nsig, ++xexp; + } + } + } + } + + _Genld(px, code, p, nsig, xexp); +} + +s16 _Ldunscale(s16* pex, _Pft* px) { + u16* ps = px; + s16 xchar = (ps[_D0] & _DMASK) >> _DOFF; + + + if (xchar == _DMAX) { + *pex = 0; + + return (ps[_D0] & _DFRAC) || ps[_D1] || ps[_D2] || ps[_D3] ? 2 : 1; + } else if (xchar > 0) { + ps[_D0] = (ps[_D0] & ~_DMASK) | 0x3FF0; + *pex = xchar - 0x3FE; + return -1; + } else if (xchar < 0) { + return 2; + } else { + *pex = 0; + return 0; + } +} + +void _Genld(_Pft* px, char code, u8* p, s16 nsig, s16 xexp) { + const unsigned char point = '.'; + + if (nsig <= 0) { + nsig = 1, p = "0"; // memes + } + + if (code == 'f' || (code == 'g' || code == 'G') && xexp >= -4 && xexp < px->prec) { + xexp += 1; + if (code != 'f') { + if (((px->flags & 8) == 0) && nsig < px->prec) { + px->prec = nsig; + } + + px->prec -= xexp; + if (px->prec < 0) { + px->prec = 0; + } + } + + if (xexp <= 0) { + px->s[px->n1++] = '0'; + + if (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1++] = point; + } + + if (px->prec < -xexp) { + xexp = -px->prec; + } + + px->nz1 = -xexp; + px->prec += xexp; + + if (px->prec < nsig) { + nsig = px->prec; + } + + memcpy(&px->s[px->n1], p, px->n2 = nsig); // , memes (this one is insane) + px->nz2 = px->prec - nsig; + } else if (nsig < xexp) { + memcpy(&px->s[px->n1], p, nsig); + px->n1 += nsig; + px->nz1 = xexp - nsig; + if (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1] = point; + px->n2 += 1; + } + + px->nz2 = px->prec; + } else { + memcpy(&px->s[px->n1], p, xexp); + px->n1 += xexp; + nsig -= xexp; + + if (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1++] = point; + } + + if (px->prec < nsig) { + nsig = px->prec; + } + + memcpy(&px->s[px->n1], &p[xexp], nsig); + px->n1 += nsig; + px->nz1 = px->prec - nsig; + } + } else { + if (code == 'g' || code == 'G') { + if (nsig < px->prec) { + px->prec = nsig; + } + + if (--px->prec < 0) { + px->prec = 0; + } + + if (code == 'g') { + code = 'e'; + } else { + code = 'E'; + } + } + + px->s[px->n1++] = *p++; + + if (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1++] = point; + } + + if (px->prec > 0) { + if (px->prec < --nsig) { + nsig = px->prec; + } + + memcpy(&px->s[px->n1], p, nsig); + px->n1 += nsig; + px->nz1 = px->prec - nsig; + } + + p = &px->s[px->n1]; + *p++ = code; + + if (xexp >= 0) { + *p++ = '+'; + } else { + *p++ = '-'; + xexp = -xexp; + } + + if (xexp >= 100) { + if (xexp >= 1000) { + *p++ = (xexp / 1000) + '0', xexp %= 1000; // , memes + } + *p++ = (xexp / 100) + '0', xexp %= 100; // , memes + } + *p++ = (xexp / 10) + '0', xexp %= 10; // , memes + + *p++ = xexp + '0'; + px->n2 = (size_t)p - ((size_t)px->s + px->n1); + } + + if ((px->flags & 0x14) == 0x10) { + s32 n = px->n0 + px->n1 + px->nz1 + px->n2 + px->nz2; + + if (n < px->width) { + px->nz0 = px->width - n; + } + } +} + diff --git a/lib/ultralib/src/libc/xlitob.c b/lib/ultralib/src/libc/xlitob.c new file mode 100755 index 0000000..f297df4 --- /dev/null +++ b/lib/ultralib/src/libc/xlitob.c @@ -0,0 +1,64 @@ +#include "stdlib.h" +#include "string.h" +#include "xstdio.h" + +// TODO: these come from headers +#ident "$Revision: 1.34 $" +#ident "$Revision: 1.5 $" +#ident "$Revision: 1.23 $" + +#define BUFF_LEN 0x18 + +static char ldigs[] = "0123456789abcdef"; +static char udigs[] = "0123456789ABCDEF"; + +void _Litob(_Pft *args, char type) { + char buff[BUFF_LEN]; + const char *digs; + s32 base; + s32 i; + unsigned long long ullval; + + if (type == 'X') { + digs = udigs; + } else { + digs = ldigs; + } + + base = (type == 'o') ? 8 : ((type != 'x' && type != 'X') ? 10 : 16); + i = BUFF_LEN; + ullval = args->v.ll; + + if ((type == 'd' || type == 'i') && args->v.ll < 0) { + ullval = -ullval; + } + + if (ullval != 0 || args->prec != 0) { + buff[--i] = digs[ullval % base]; + } + + args->v.ll = ullval / base; + + while (args->v.ll > 0 && i > 0) { + lldiv_t qr = lldiv(args->v.ll, base); + + args->v.ll = qr.quot; + buff[--i] = digs[qr.rem]; + } + + args->n1 = BUFF_LEN - i; + + memcpy(args->s, buff + i, args->n1); + + if (args->n1 < args->prec) { + args->nz0 = args->prec - args->n1; + } + + if (args->prec < 0 && (args->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) { + i = args->width - args->n0 - args->nz0 - args->n1; + + if (i > 0) { + args->nz0 += i; + } + } +} diff --git a/lib/ultralib/src/libc/xprintf.c b/lib/ultralib/src/libc/xprintf.c new file mode 100755 index 0000000..d9f1003 --- /dev/null +++ b/lib/ultralib/src/libc/xprintf.c @@ -0,0 +1,241 @@ +#include "macros.h" +#include "string.h" +#include "stdarg.h" +#include "xstdio.h" + +// TODO: these come from headers +#ident "$Revision: 1.34 $" +#ident "$Revision: 1.5 $" +#ident "$Revision: 1.23 $" + +#define isdigit(x) ((x >= '0' && x <= '9')) +#define LDSIGN(x) (((unsigned short *)&(x))[0] & 0x8000) + +#define ATOI(dst, src) \ + for (dst = 0; isdigit(*src); ++src) \ + { \ + if (dst < 999) \ + dst = dst * 10 + *src - '0'; \ + } + +#define MAX_PAD ((sizeof(spaces) - 1)) +#define PAD(s, n) \ + if (0 < (n)) \ + { \ + int i, j = (n); \ + for (; 0 < j; j -= i) \ + { \ + i = MAX_PAD < (unsigned int)j ? (int)MAX_PAD : j; \ + PUT(s, i); \ + } \ + } +#define PUT(s, n) \ + if (0 < (n)) \ + { \ + if ((arg = (*prout)(arg, s, n)) != NULL) \ + x.nchar += (n); \ + else \ + return x.nchar; \ + } +static char spaces[] = " "; +static char zeroes[] = "00000000000000000000000000000000"; + +static void _Putfld(_Pft *pf, va_list *pap, char code, char *ac); + +int _Printf(outfun prout, char *arg, const char *fmt, va_list args) { + _Pft x; + const char *s; + char c; + const char *t; + static const char fchar[] = {' ', '+', '-', '#', '0', '\0'}; + static const int fbit[] = {FLAGS_SPACE, FLAGS_PLUS, FLAGS_MINUS, FLAGS_HASH, FLAGS_ZERO, 0}; + char ac[32]; + + x.nchar = 0; + + for (;;) { + s = fmt; + + for (c = *s; c != 0 && c != '%';) { + c = *++s; + } + + PUT(fmt, s - fmt); + + if (c == 0) { + return x.nchar; + } + + fmt = ++s; + + for (x.flags = 0; (t = strchr(fchar, *s)) != NULL; s++) { + x.flags |= fbit[t - fchar]; + } + + if (*s == '*') { + x.width = va_arg(args, int); + + if (x.width < 0) { + x.width = -x.width; + x.flags |= FLAGS_MINUS; + } + s++; + } else { + ATOI(x.width, s); + } + + if (*s != '.') { + x.prec = -1; + } else if (*++s == '*') { + x.prec = va_arg(args, int); + ++s; + } else { + ATOI(x.prec, s); + } + + x.qual = strchr("hlL", *s) ? *s++ : '\0'; + + if (x.qual == 'l' && *s == 'l') { + x.qual = 'L'; + ++s; + } + + _Putfld(&x, &args, *s, ac); + x.width -= x.n0 + x.nz0 + x.n1 + x.nz1 + x.n2 + x.nz2; + + if (!(x.flags & FLAGS_MINUS)) { + PAD(spaces, x.width); + } + + PUT(ac, x.n0); + PAD(zeroes, x.nz0); + PUT(x.s, x.n1); + PAD(zeroes, x.nz1); + PUT(x.s + x.n1, x.n2); + PAD(zeroes, x.nz2); + + if (x.flags & FLAGS_MINUS) { + PAD(spaces, x.width); + } + + fmt = s + 1; + } + return 0; +} + +static void _Putfld(_Pft *x, va_list *args, char type, char *buff) { + x->n0 = x->nz0 = x->n1 = x->nz1 = x->n2 = + x->nz2 = 0; + + switch (type) { + case 'c': + buff[x->n0++] = va_arg(*args, int); + break; + case 'd': + case 'i': + if (x->qual == 'l') { + x->v.ll = va_arg(*args, int); + } else if (x->qual == 'L') { + x->v.ll = va_arg(*args, s64); + } else { + x->v.ll = va_arg(*args, int); + } + + if (x->qual == 'h') { + x->v.ll = (s16)x->v.ll; + } + + if (x->v.ll < 0) { + buff[x->n0++] = '-'; + } else if (x->flags & FLAGS_PLUS) { + buff[x->n0++] = '+'; + } else if (x->flags & FLAGS_SPACE) { + buff[x->n0++] = ' '; + } + + x->s = (char *)&buff[x->n0]; + + _Litob(x, type); + break; + case 'x': + case 'X': + case 'u': + case 'o': + if (x->qual == 'l') { + x->v.ll = va_arg(*args, int); + } else if (x->qual == 'L') { + x->v.ll = va_arg(*args, s64); + } else { + x->v.ll = va_arg(*args, int); + } + + if (x->qual == 'h') { + x->v.ll = (u16)x->v.ll; + } else if (x->qual == 0) { + x->v.ll = (unsigned int)x->v.ll; + } + + if (x->flags & FLAGS_HASH) { + buff[x->n0++] = '0'; + + if (type == 'x' || type == 'X') { + buff[x->n0++] = type; + } + } + + x->s = (char *)&buff[x->n0]; + _Litob(x, type); + break; + case 'e': + case 'f': + case 'g': + case 'E': + case 'G': + //... okay? + x->v.ld = x->qual == 'L' ? va_arg(*args, f64) : va_arg(*args, f64); + + if (LDSIGN(x->v.ld)) + buff[x->n0++] = '-'; + else if (x->flags & FLAGS_PLUS) + buff[x->n0++] = '+'; + else if (x->flags & FLAGS_SPACE) + buff[x->n0++] = ' '; + + x->s = (char *)&buff[x->n0]; + _Ldtob(x, type); + break; + + case 'n': + if (x->qual == 'h') { + *(va_arg(*args, u16 *)) = x->nchar; + } else if (x->qual == 'l') { + *va_arg(*args, unsigned int *) = x->nchar; + } else if (x->qual == 'L') { + *va_arg(*args, u64 *) = x->nchar; + } else { + *va_arg(*args, unsigned int *) = x->nchar; + } + + break; + case 'p': + x->v.ll = (long)va_arg(*args, void *); + x->s = (char *)&buff[x->n0]; + _Litob(x, 'x'); + break; + case 's': + x->s = va_arg(*args, char *); + x->n1 = strlen(x->s); + + if (x->prec >= 0 && x->n1 > x->prec) { + x->n1 = x->prec; + } + + break; + case '%': + buff[x->n0++] = '%'; + break; + default: + buff[x->n0++] = type; + break; + } +} diff --git a/lib/ultralib/src/libc/xstdio.h b/lib/ultralib/src/libc/xstdio.h new file mode 100755 index 0000000..bd70de8 --- /dev/null +++ b/lib/ultralib/src/libc/xstdio.h @@ -0,0 +1,37 @@ +#ifndef _XSTDIO_H +#define _XSTDIO_H +#include "PR/ultratypes.h" +#include "stdlib.h" +#include "stdarg.h" + +typedef struct { + /* 0x0 */ union { + /* 0x0 */ long long ll; + /* 0x0 */ double ld; + } v; + /* 0x8 */ unsigned char* s; + /* 0xC */ int n0; + /* 0x10 */ int nz0; + /* 0x14 */ int n1; + /* 0x18 */ int nz1; + /* 0x1C */ int n2; + /* 0x20 */ int nz2; + /* 0x24 */ int prec; + /* 0x28 */ int width; + /* 0x2C */ size_t nchar; + /* 0x30 */ unsigned int flags; + /* 0x34 */ char qual; +} _Pft; + +#define FLAGS_SPACE 1 +#define FLAGS_PLUS 2 +#define FLAGS_MINUS 4 +#define FLAGS_HASH 8 +#define FLAGS_ZERO 16 +typedef char *outfun(char*,const char*,size_t); + +int _Printf(outfun prout, char *arg, const char *fmt, va_list args); +void _Litob(_Pft *args, char type); +void _Ldtob(_Pft* args, char type); + +#endif diff --git a/lib/ultralib/src/mgu/Makefile b/lib/ultralib/src/mgu/Makefile new file mode 100644 index 0000000..52c29f6 --- /dev/null +++ b/lib/ultralib/src/mgu/Makefile @@ -0,0 +1,36 @@ +# +# Makefile for the gu subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + +LCINCS = -I. -I../gu -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include +LASINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/include +LCOPTS = -G 0 -g -O + +CFILES = mtxcatl.c \ + mtxxfml.c \ + mtxxfmf.c \ + rotate.c + +ASFILES = mtxident.s \ + mtxidentf.s \ + mtxf2l.s \ + mtxl2f.s \ + mtxcatf.s \ + scale.s \ + scalef.s \ + normalize.s \ + translate.s \ + translatef.s + +OBJECTS = $(CFILES:.c=.o) $(ASFILES:.s=.o) + +default: $(OBJECTS) + +include $(COMMONRULES) + +.s.o: + cpp $(F_ROM) -DLANG_JAPANESE -E -DMIPSEB -DLANGUAGE_ASSEMBLY -D_MIPS_SIM=1 -D_ULTRA64 -I. -I$(LIBDEPTH)\include $*.s $*.ss2 + as -mips3 -G0 -o $*.o $*.ss2 + del $*.ss? diff --git a/lib/ultralib/src/mgu/asm.h b/lib/ultralib/src/mgu/asm.h new file mode 100644 index 0000000..0c417fa --- /dev/null +++ b/lib/ultralib/src/mgu/asm.h @@ -0,0 +1,49 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO Co,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO Co,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO Co,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/07/06 13:21:13 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#ifndef __ASM_H__ +#define __ASM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define _MIPS_ISA_MIPS1 1 /* R2/3K */ +#define _MIPS_ISA_MIPS2 2 /* R4K/6K */ +#define _MIPS_ISA_MIPS3 3 /* R4K */ +#define _MIPS_ISA_MIPS4 4 /* TFP */ + +#define _MIPS_SIM_ABI32 1 /* MIPS MSIG calling convention */ +#define _MIPS_SIM_NABI32 2 /* MIPS new 32-bit abi */ + /* NABI32 is 64bit calling convention but 32bit type sizes) */ +#define _MIPS_SIM_ABI64 3 /* MIPS 64 calling convention */ + +#define LEAF(x) \ + .globl x; \ + .ent x,0; \ +x:; \ + .frame sp,0,ra + +#define END(proc) \ + .end proc + + +#ifdef __cplusplus +} +#endif + +#endif /* !__ASM_H__ */ diff --git a/lib/ultralib/src/mgu/mtxcatf.s b/lib/ultralib/src/mgu/mtxcatf.s new file mode 100644 index 0000000..4b96124 --- /dev/null +++ b/lib/ultralib/src/mgu/mtxcatf.s @@ -0,0 +1,103 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:37 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#include <asm.h> +#include <regdef.h> + +/* + * void guMtxCatF(float mf[4][4], float nf[4][4], float res[4][4]) + * res = mf * nf + */ +#define FRAME_SIZE 64 + .text + .align 5 + .globl guMtxCatF + .ent guMtxCatF, 0 +guMtxCatF: + .set reorder + subu sp, FRAME_SIZE + .frame sp, FRAME_SIZE, ra + + addu v0, a0, 64 + addu v1, a1, 16 + move t2, sp +label_loop_i: + move a3, a1 +label_loop_j: + l.s ft0, 0(a0) /* mf[i][0] * nf[0][j] */ + l.s ft1, 0(a3) + mul.s ft2, ft0, ft1 + l.s ft3, 4(a0) /* + mf[i][1] * nf[1][j] */ + l.s ft4, 16(a3) + mul.s ft5, ft3, ft4 + add.s ft2, ft2, ft5 + l.s ft0, 8(a0) /* + mf[i][2] * nf[2][j] */ + l.s ft1, 32(a3) + mul.s ft5, ft0, ft1 + add.s ft2, ft2, ft5 + l.s ft3, 12(a0) /* + mf[i][3] * nf[3][j] */ + l.s ft4, 48(a3) + mul.s ft5, ft3, ft4 + add.s ft2, ft2, ft5 + + s.s ft2, 0(t2) + addu a3, a3, 4 + addu t2, t2, 4 + bne a3, v1, label_loop_j +/* loop_j_end */ + addu a0, a0, 16 + bne a0, v0, label_loop_i +/* loop_i_end */ + s.s ft2, 60(a2) + lw t0, 0(sp) + lw t1, 4(sp) + lw t2, 8(sp) + lw t3, 12(sp) + lw ta0, 16(sp) + lw ta1, 20(sp) + lw ta2, 24(sp) + lw ta3, 28(sp) + lw t8, 32(sp) + lw t9, 36(sp) + lw v0, 40(sp) + lw v1, 44(sp) + lw a0, 48(sp) + lw a1, 52(sp) + lw a3, 56(sp) + + sw t0, 0(a2) + sw t1, 4(a2) + sw t2, 8(a2) + sw t3, 12(a2) + sw ta0, 16(a2) + sw ta1, 20(a2) + sw ta2, 24(a2) + sw ta3, 28(a2) + sw t8, 32(a2) + sw t9, 36(a2) + sw v0, 40(a2) + sw v1, 44(a2) + sw a0, 48(a2) + sw a1, 52(a2) + sw a3, 56(a2) + + addu sp , FRAME_SIZE + j ra + + .end guMtxCatF + +/* end of file */ diff --git a/lib/ultralib/src/mgu/mtxcatl.c b/lib/ultralib/src/mgu/mtxcatl.c new file mode 100644 index 0000000..86a978a --- /dev/null +++ b/lib/ultralib/src/mgu/mtxcatl.c @@ -0,0 +1,34 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:37 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#include <ultra64.h> +#include "../gu/guint.h" +#include "gu.h" + +void guMtxCatL(Mtx *m, Mtx *n, Mtx *res) +{ + float mf[4][4], nf[4][4], resf[4][4]; + + guMtxL2F(mf, m); + guMtxL2F(nf, n); + + guMtxCatF(mf, nf, resf); + + guMtxF2L(resf, res); +} + +/* End of file */ diff --git a/lib/ultralib/src/mgu/mtxf2l.s b/lib/ultralib/src/mgu/mtxf2l.s new file mode 100644 index 0000000..43bbe7e --- /dev/null +++ b/lib/ultralib/src/mgu/mtxf2l.s @@ -0,0 +1,80 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:38 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#include <asm.h> +#include <regdef.h> + +/* + * void guMtxF2L(float mf[4][4], Mtx *m) + * + * Input + * float mf[4][4] + * Output + * Mtx *m + */ + +#define HALF_SIZE_MTX 32 +#define MASK_LOW 0x0000FFFF +#define MASK_HIGH 0xFFFF0000 +#define MAGNIFICANT 65536.0 /* = 0x10000 */ + +#define ptr_fl a0 /* argument */ +#define ptr_mtx a1 /* argument */ +#define end_mtx t8 +#define mask_hi t9 +#define magni fv0 + + .text + .align 5 +LEAF( guMtxF2L ) + .set reorder + + li.s magni, MAGNIFICANT + li mask_hi, MASK_HIGH + addu end_mtx, ptr_mtx, HALF_SIZE_MTX +label_loop: + l.s ft0, 0(ptr_fl) /* FTOFIX32( ) */ + mul.s ft1, ft0, magni + trunc.w.s ft2, ft1 + + l.s ft3, 4(ptr_fl) /* FTOFIX32( ) */ + mul.s ft4, ft3, magni + trunc.w.s ft5, ft4 + + mfc1 t0, ft2 /* t0 <- FIXED */ + mfc1 t1, ft5 /* t1 <- FIXED */ + + and t2, t0, mask_hi /* integral part */ + srl t3, t1, 16 + or ta0, t2, t3 + sw ta0, 0(ptr_mtx) + + sll ta1, t0, 16 /* decimal part */ + and ta2, t1, MASK_LOW + or ta3, ta1, ta2 + sw ta3, HALF_SIZE_MTX(ptr_mtx) + + addu ptr_mtx, ptr_mtx, 4 + addu ptr_fl, ptr_fl, 8 + + bne ptr_mtx, end_mtx, label_loop +/* loop-end */ + + j ra + END( guMtxF2L ) + +/* End of file */ diff --git a/lib/ultralib/src/mgu/mtxident.s b/lib/ultralib/src/mgu/mtxident.s new file mode 100644 index 0000000..a9ec491 --- /dev/null +++ b/lib/ultralib/src/mgu/mtxident.s @@ -0,0 +1,60 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:38 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * void guMtxIdent( Mtx * matrix ) + * Substitute unit matrix for matrix + * Correspond only when alignment is 4 byte boundary + * Input + * a0 = matrix + * Output + * *matrix unit matrix + */ + +#define SIZE_OF_MTX 64 /* sizeof( Mtx ) */ + .text + .align 5 +LEAF(guMtxIdent) + .set reorder + + addi t0, zero, 1 /* t0 = 0x00000001 */ + sll t1, t0, 16 /* t1 = 0x00010000 */ + + sw t1, 0(a0) /* Substitution of integers */ + sw zero, 4(a0) + sw t0, 8(a0) + sw zero, 12(a0) + sw zero, 16(a0) + sw t1, 20(a0) + sw zero, 24(a0) + sw t0, 28(a0) + + sw zero, 32(a0) /* Substitution of fractions */ + sw zero, 36(a0) + sw zero, 40(a0) + sw zero, 44(a0) + sw zero, 48(a0) + sw zero, 52(a0) + sw zero, 56(a0) + sw zero, 60(a0) + j ra + + END(guMtxIdent) + +/* End of file */ diff --git a/lib/ultralib/src/mgu/mtxidentf.s b/lib/ultralib/src/mgu/mtxidentf.s new file mode 100644 index 0000000..a6aa779 --- /dev/null +++ b/lib/ultralib/src/mgu/mtxidentf.s @@ -0,0 +1,60 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:38 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * guMtxIdentF( float matrix[4][4] ) + * substitute unit matrix for floating point matrix + * correspond only when alignment is four byte boundary + * Input + * a0 = matrix + * Output + * *matrix unti matix + */ + .text + .align 5 +LEAF( guMtxIdentF ) + .set reorder + + li t0, 0x3f800000 /* t0 = 1.0 */ + + sw t0, 0(a0) + sw zero, 4(a0) /* line 1 */ + sw zero, 8(a0) + sw zero, 12(a0) + + sw zero, 16(a0) /* line 2 */ + sw t0, 20(a0) + sw zero, 24(a0) + sw zero, 28(a0) + + sw zero, 32(a0) /* line 3 */ + sw zero, 36(a0) + sw t0, 40(a0) + sw zero, 44(a0) + + sw zero, 48(a0) /* line 4 */ + sw zero, 52(a0) + sw zero, 56(a0) + sw t0, 60(a0) + + j ra + + END( guMtxIdentF ) + +/* End of file */
\ No newline at end of file diff --git a/lib/ultralib/src/mgu/mtxl2f.s b/lib/ultralib/src/mgu/mtxl2f.s new file mode 100644 index 0000000..897acfb --- /dev/null +++ b/lib/ultralib/src/mgu/mtxl2f.s @@ -0,0 +1,80 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:38 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#include <asm.h> +#include <regdef.h> + +/* + * void guMtxF2L(float mf[4][4], Mtx *m) + * + * Input + * float mf[4][4] + * Output + * Mtx *m + */ + +#define HALF_SIZE_MTX 32 +#define MASK_LOW 0x0000FFFF +#define MASK_HIGH 0xFFFF0000 +#define MAGNIFICANT 1.5258789062500000e-05 /* ~ 1 / 0x10000 */ + +#define ptr_fl a0 /* argument */ +#define ptr_mtx a1 /* argument */ +#define end_mtx t8 +#define mask_hi t9 +#define magni fv0 + + .text + .align 5 +LEAF( guMtxL2F ) + .set reorder + li.s magni, MAGNIFICANT + li mask_hi, MASK_HIGH + addu end_mtx, ptr_mtx, HALF_SIZE_MTX +label_loop: + lw t0, 0(ptr_mtx) + lw t1, 32(ptr_mtx) + + and t2, t0, mask_hi + srl t3, t1, 16 + or ta0, t2, t3 + + sll ta1, t0, 16 + and ta2, t1, MASK_LOW + or ta3, ta1, ta2 + + mtc1 ta0, ft0 /* FIX32TOF( ) */ + cvt.s.w ft1, ft0 + mul.s ft2, ft1, magni + + mtc1 ta3, ft3 /* FIX32TOF( ) */ + cvt.s.w ft4, ft3 + mul.s ft5, ft4, magni + + s.s ft2, 0(ptr_fl) + s.s ft5, 4(ptr_fl) + + addu ptr_mtx, ptr_mtx, 4 + addu ptr_fl, ptr_fl, 8 + + bne ptr_mtx, end_mtx, label_loop +/* loop-end */ + + j ra + END( guMtxL2F ) + +/* End of file */ diff --git a/lib/ultralib/src/mgu/mtxxfmf.c b/lib/ultralib/src/mgu/mtxxfmf.c new file mode 100644 index 0000000..58c6772 --- /dev/null +++ b/lib/ultralib/src/mgu/mtxxfmf.c @@ -0,0 +1,40 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + * + */ + +/* + * File: mtxcatf.c + * Creator: hsa@sgi.com + * Create Date: Thu Nov 2 13:03:02 PST 1995 + * + */ + +#include "../gu/guint.h" + +void guMtxXFMF(float mf[4][4], float x, float y, float z, float *ox, float *oy, float *oz) +{ + *ox = mf[0][0]*x + mf[1][0]*y + mf[2][0]*z + mf[3][0]; + *oy = mf[0][1]*x + mf[1][1]*y + mf[2][1]*z + mf[3][1]; + *oz = mf[0][2]*x + mf[1][2]*y + mf[2][2]*z + mf[3][2]; +} + diff --git a/lib/ultralib/src/mgu/mtxxfml.c b/lib/ultralib/src/mgu/mtxxfml.c new file mode 100644 index 0000000..1dfa871 --- /dev/null +++ b/lib/ultralib/src/mgu/mtxxfml.c @@ -0,0 +1,41 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + * + */ + +/* + * File: mtxcatl.c + * Creator: hsa@sgi.com + * Create Date: Thu Nov 2 13:03:02 PST 1995 + * + */ + +#include "../gu/guint.h" + +void guMtxXFML(Mtx *m, float x, float y, float z, float *ox, float *oy, float *oz) +{ + float mf[4][4]; + + guMtxL2F(mf, m); + + guMtxXFMF(mf, x, y, z, ox, oy, oz); +} diff --git a/lib/ultralib/src/mgu/normalize.s b/lib/ultralib/src/mgu/normalize.s new file mode 100644 index 0000000..58b9093 --- /dev/null +++ b/lib/ultralib/src/mgu/normalize.s @@ -0,0 +1,56 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:39 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * void guNormalize(float *x, float *y, float *z) + */ + .text + .align 5 +LEAF( guNormalize ) + .set noreorder + + l.s ft0, 0(a0) /* ft0 = x */ + l.s ft1, 0(a1) /* ft1 = y */ + l.s ft2, 0(a2) /* ft2 = z */ + + mul.s ft3, ft0, ft0 /* ft3 = x*x */ + lui t0, 0x3f80 /* t0 = 1.0f */ + mul.s ft4, ft1, ft1 /* ft4 = y*y */ + add.s ft5, ft3, ft4 + mul.s ft4, ft2, ft2 /* ft4 = z*z */ + + add.s ft3, ft4, ft5 /* ft3 = x*x + y*y + z*z */ + mtc1 t0, ft5 + sqrt.s ft4, ft3 /* ft4 = sqrt(x*x + y*y + z*z) */ + + div.s ft3, ft5, ft4 /* ft3 = 1/sqrt(x*x + y*y + z*z) */ + + mul.s ft4, ft0, ft3 /* ft4 = x * 1/sqrt(x*x + y*y + z*z) */ + nop + mul.s ft5, ft1, ft3 /* ft5 = y * 1/sqrt(x*x + y*y + z*z) */ + nop + mul.s ft0, ft2, ft3 /* ft0 = z * 1/sqrt(x*x + y*y + z*z) */ + + s.s ft4, 0(a0) /* x = ft4 */ + s.s ft5, 0(a1) /* y = ft5 */ + j ra + s.s ft0, 0(a2) /* z = ft0 */ /* Use delayed slot */ + + END( guNormalize ) +/* end of file */ diff --git a/lib/ultralib/src/mgu/regdef.h b/lib/ultralib/src/mgu/regdef.h new file mode 100644 index 0000000..ac9c109 --- /dev/null +++ b/lib/ultralib/src/mgu/regdef.h @@ -0,0 +1,187 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO Co,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO Co,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO Co,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/07/06 13:21:13 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#ifndef __REGDEF_H__ +#define __REGDEF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef mips + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define zero $0 +#define AT $at +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define ta0 $12 +#define t5 $13 +#define ta1 $13 +#define t6 $14 +#define ta2 $14 +#define t7 $15 +#define ta3 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define jp $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI64) +#define zero $0 +#define AT $at +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define a4 $8 +#define ta0 $8 +#define a5 $9 +#define ta1 $9 +#define a6 $10 +#define ta2 $10 +#define a7 $11 +#define ta3 $11 +#define t0 $12 +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define jp $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define fv0 $f0 +#define fv0f $f1 +#define fv1 $f2 +#define fv1f $f3 +#define fa0 $f12 +#define fa0f $f13 +#define fa1 $f14 +#define fa1f $f15 +#define ft0 $f4 +#define ft0f $f5 +#define ft1 $f6 +#define ft1f $f7 +#define ft2 $f8 +#define ft2f $f9 +#define ft3 $f10 +#define ft3f $f11 +#define ft4 $f16 +#define ft4f $f17 +#define ft5 $f18 +#define ft5f $f19 +#define fs0 $f20 +#define fs0f $f21 +#define fs1 $f22 +#define fs1f $f23 +#define fs2 $f24 +#define fs2f $f25 +#define fs3 $f26 +#define fs3f $f27 +#define fs4 $f28 +#define fs4f $f29 +#define fs5 $f30 +#define fs5f $f31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI64) +#define fv0 $f0 +#define fv1 $f2 +#define fa0 $f12 +#define fa1 $f13 +#define fa2 $f14 +#define fa3 $f15 +#define fa4 $f16 +#define fa5 $f17 +#define fa6 $f18 +#define fa7 $f19 +#define ft0 $f4 +#define ft1 $f5 +#define ft2 $f6 +#define ft3 $f7 +#define ft4 $f8 +#define ft5 $f9 +#define ft6 $f10 +#define ft7 $f11 +#define ft8 $f20 +#define ft9 $f21 +#define ft10 $f22 +#define ft11 $f23 +#define ft12 $f1 +#define ft13 $f3 +#define fs0 $f24 +#define fs1 $f25 +#define fs2 $f26 +#define fs3 $f27 +#define fs4 $f28 +#define fs5 $f29 +#define fs6 $f30 +#define fs7 $f31 +#endif + +#define fcr31 $31 + +#endif /* mips */ + +#ifdef __cplusplus +} +#endif + +#endif /* !__REGDEF_H__ */ diff --git a/lib/ultralib/src/mgu/rotate.c b/lib/ultralib/src/mgu/rotate.c new file mode 100644 index 0000000..fec2443 --- /dev/null +++ b/lib/ultralib/src/mgu/rotate.c @@ -0,0 +1,64 @@ +/************************************************************************** + * * + * 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 "../gu/guint.h" +#include "gu.h" + +void guRotateF(float mf[4][4], float a, float x, float y, float z) +{ + static float dtor = 3.1415926 / 180.0; + float sine; + float cosine; + float ab, bc, ca, t; + float xxsine; + float yxsine; + float zxsine; + + guNormalize(&x, &y, &z); + a *= dtor; + sine = sinf(a); + cosine = cosf(a); + t = (1-cosine); + ab = x*y*t; + bc = y*z*t; + ca = z*x*t; + + guMtxIdentF(mf); + + xxsine = x * sine; + yxsine = y * sine; + zxsine = z * sine; + + t = x*x; + mf[0][0] = t+cosine*(1-t); + mf[2][1] = bc-xxsine; + mf[1][2] = bc+xxsine; + + t = y*y; + mf[1][1] = t+cosine*(1-t); + mf[2][0] = ca+yxsine; + mf[0][2] = ca-yxsine; + + t = z*z; + mf[2][2] = t+cosine*(1-t); + mf[1][0] = ab-zxsine; + mf[0][1] = ab+zxsine; +} + +void guRotate(Mtx *m, float a, float x, float y, float z) +{ + Matrix mf; + + guRotateF(mf, a, x, y, z); + + guMtxF2L(mf, m); +} diff --git a/lib/ultralib/src/mgu/scale.s b/lib/ultralib/src/mgu/scale.s new file mode 100644 index 0000000..01bc290 --- /dev/null +++ b/lib/ultralib/src/mgu/scale.s @@ -0,0 +1,85 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:40 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * FTOFIX32 (float to fix32) + * a: input + * t: output + * ft0 : (float)0x00010000 + * ft1, ft2, ft3, t0 : work reg + */ +#define FTOFIX32(a, t) \ + mtc1 a, ft1 ; \ + mul.s ft2, ft1, ft0 ; \ + trunc.w.s ft3, ft2, t0 ; \ + mfc1 t, ft3 ; + +/* + void guScale(Mtx *m, float x, float y, float z) + m: a0 + x: a1 + y: a2 + z a3 + */ +#define SIZE_OF_MTX 64 /* sizeof( Mtx ) */ +#define FLOAT_0x10000 6.5536e+04 /* (float)0x00010000) */ + + .text + .align 5 +LEAF( guScale ) + .set reorder + + li.s ft0, FLOAT_0x10000 /* (float)0x00010000 */ + + FTOFIX32(a1, t1) /* t1 = FTOFIX32(x) */ + srl t2, t1, 16 + sll t0, t2, 16 + sw t0, 0(a0) /* t0 = x integral part */ + sll t2, t1, 16 + sw t2, 32(a0) /* t2 = x decimal part */ + + FTOFIX32(a2, t1) /* t1 = FTOFIX32(y) */ + srl t0, t1, 16 + sw t0, 8(a0) /* t0 = y integral part */ + andi t2, t1, 0xffff + sw t2, 40(a0) /* t2 = y decimal part */ + + FTOFIX32(a3, t1) /* t1 = FTOFIX32(z) */ + srl t2, t1, 16 + sll t0, t2, 16 + sw t0, 20(a0) /* t0 = z integral part */ + sll t2, t1, 16 + sw t2, 52(a0) /* t2 = z decimal part */ + + li t0, 1 /* t0 = 1.0 integral part */ + sw t0, 28(a0) + + sw zero, 4(a0) + sw zero, 12(a0) + sw zero, 16(a0) + sw zero, 24(a0) + sw zero, 36(a0) + sw zero, 44(a0) + sw zero, 48(a0) + sw zero, 56(a0) + sw zero, 60(a0) + j ra + + END( guScale ) +/* end of file */ diff --git a/lib/ultralib/src/mgu/scalef.s b/lib/ultralib/src/mgu/scalef.s new file mode 100644 index 0000000..b27d1e3 --- /dev/null +++ b/lib/ultralib/src/mgu/scalef.s @@ -0,0 +1,57 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:40 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * void guScaleF(float m[4][4], float x, float y, float z) + * m: a0 + * x: a1 + * y: a2 + * z: a3 + */ + .text + .align 5 +LEAF( guScaleF ) + .set reorder + + sw a1, 0(a0) + sw zero, 4(a0) /* line 1 */ + sw zero, 8(a0) + sw zero, 12(a0) + + sw zero, 16(a0) /* line 2 */ + sw a2, 20(a0) + sw zero, 24(a0) + sw zero, 28(a0) + + sw zero, 32(a0) /* line 3 */ + sw zero, 36(a0) + sw a3, 40(a0) + sw zero, 44(a0) + + li t0, 0x3f800000 /* t0 = 1.0 */ + sw zero, 48(a0) /* line 4 */ + sw zero, 52(a0) + sw zero, 56(a0) + sw t0, 60(a0) + + j ra + + END( guScaleF ) + +/* End of file */ diff --git a/lib/ultralib/src/mgu/translate.s b/lib/ultralib/src/mgu/translate.s new file mode 100644 index 0000000..472fd8c --- /dev/null +++ b/lib/ultralib/src/mgu/translate.s @@ -0,0 +1,101 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:40 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + void guTranslate(Mtx *m, float x, float y, float z) + m: a0 + x: a1 + y: a2 + z a3 + */ + +#define SIZE_OF_MTX 64 /* sizeof( Mtx ) */ +#define FLOAT_0x10000 6.5536e+04 /* (float)0x00010000) */ + + .text + .align 5 +LEAF( guTranslate ) + .set reorder + + li.s ft0, FLOAT_0x10000 /* (float)0x00010000 */ + + mtc1 a1, ft1 + mul.s ft2, ft1, ft0 + trunc.w.s ft3, ft2 + mfc1 t1, ft3 /* t1 = FTOFIX32(x) */ + + mtc1 a2, ft1 + mul.s ft2, ft1, ft0 + trunc.w.s ft3, ft2 + mfc1 t3, ft3 /* t3 = FTOFIX32(y) */ + + /* Save t1 and t3 values until fraction process is finished! */ + + srl t2, t1, 16 /* x integeral part for t0 interger */ + sll t0, t2, 16 + srl t2, t3, 16 /* y integral part for t2 fraction */ + or t0, t0, t2 /* Compose in t0 */ + sw t0, 24(a0) + + sll t0,t1,16 /* x fraction part for t0 interger */ + sll t2,t3,16 + srl t2,t2,16 /* y fraction part for t2 fraction */ + or t0,t0,t2 /* Compose in t0 */ + sw t0,24+32(a0) + + + mtc1 a3, ft1 + mul.s ft2, ft1, ft0 + trunc.w.s ft3, ft2 + mfc1 t1, ft3 /* t1 = FTOFIX32(z) */ + + srl t2,t1,16 + sll t0,t2,16 /* z integral part for t0 integer */ + addiu t0,t0,1 /* enter 0x0001 in t0 fraction */ + sw t0,28(a0) + + sll t2,t1,16 /* z fraction part for t2 integer */ + sw t2,28+32(a0) + + sw zero, 0(a0) + sw zero, 4(a0) + sw zero, 8(a0) + sw zero, 12(a0) + sw zero, 16(a0) + sw zero, 20(a0) + sw zero, 0+32(a0) + sw zero, 4+32(a0) + sw zero, 8+32(a0) + sw zero, 12+32(a0) + sw zero, 16+32(a0) + sw zero, 20+32(a0) + + lui t0,0x0001 + ori t0,0x0000 + sw t0,0(a0) + sw t0,20(a0) + + lui t0,0x0000 + ori t0,0x0001 + sw t0,8(a0) + + j ra + + END( guTranslate ) +/* end of file */ diff --git a/lib/ultralib/src/mgu/translatef.s b/lib/ultralib/src/mgu/translatef.s new file mode 100644 index 0000000..47d14bd --- /dev/null +++ b/lib/ultralib/src/mgu/translatef.s @@ -0,0 +1,58 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO CO,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO CO,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO CO,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/06/16 09:15:41 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ +#include <asm.h> +#include <regdef.h> + +/* + * void guTranslateF(float m[4][4], float x, float y, float z) + * m: a0 + * x: a1 + * y: a2 + * z: a3 + */ + .text + .align 5 +LEAF( guTranslateF ) + .set reorder + + li t0,0x3f800000 /* t0 = 1.0 */ + + sw t0, 0(a0) + sw zero, 4(a0) /* line 1 */ + sw zero, 8(a0) + sw zero, 12(a0) + + sw zero, 16(a0) /* line 2 */ + sw t0, 20(a0) + sw zero, 24(a0) + sw zero, 28(a0) + + sw zero, 32(a0) /* line 3 */ + sw zero, 36(a0) + sw t0, 40(a0) + sw zero, 44(a0) + + sw a1, 48(a0) /* line 4 */ + sw a2, 52(a0) + sw a3, 56(a0) + sw t0, 60(a0) + + j ra + + END( guTranslateF ) + +/* End of file */ diff --git a/lib/ultralib/src/os/ackramromread.c b/lib/ultralib/src/os/ackramromread.c new file mode 100644 index 0000000..4aea863 --- /dev/null +++ b/lib/ultralib/src/os/ackramromread.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +void osAckRamromRead() { + +} diff --git a/lib/ultralib/src/os/ackramromwrite.c b/lib/ultralib/src/os/ackramromwrite.c new file mode 100644 index 0000000..34fe2ad --- /dev/null +++ b/lib/ultralib/src/os/ackramromwrite.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +void osAckRamromWrite() { + +} diff --git a/lib/ultralib/src/os/afterprenmi.c b/lib/ultralib/src/os/afterprenmi.c new file mode 100644 index 0000000..03b5b24 --- /dev/null +++ b/lib/ultralib/src/os/afterprenmi.c @@ -0,0 +1,5 @@ +#include "PR/os_internal.h" + +s32 osAfterPreNMI() { + return __osSpSetPc(0); +} diff --git a/lib/ultralib/src/os/assert.c b/lib/ultralib/src/os/assert.c new file mode 100644 index 0000000..d076a24 --- /dev/null +++ b/lib/ultralib/src/os/assert.c @@ -0,0 +1,5 @@ +#include "PR/os_internal.h" + +void __assert(const char *exp, const char *filename, int line) { + osSyncPrintf("\nASSERTION FAULT: %s, %d: \"%s\"\n", filename, line, exp); +} diff --git a/lib/ultralib/src/os/atomic.c b/lib/ultralib/src/os/atomic.c new file mode 100644 index 0000000..f96bb63 --- /dev/null +++ b/lib/ultralib/src/os/atomic.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" + +int __osAtomicDec(unsigned int *p) { + register u32 saveMask = __osDisableInt(); + int mask; + + if (*p) { + (*p)--; + mask = 1; + } else { + mask = 0; + } + __osRestoreInt(saveMask); + return mask; +} diff --git a/lib/ultralib/src/os/createmesgqueue.c b/lib/ultralib/src/os/createmesgqueue.c new file mode 100644 index 0000000..4e71cba --- /dev/null +++ b/lib/ultralib/src/os/createmesgqueue.c @@ -0,0 +1,11 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osCreateMesgQueue(OSMesgQueue *mq, OSMesg *msg, s32 msgCount) { + mq->mtqueue = &__osThreadTail.next; + mq->fullqueue = &__osThreadTail.next; + mq->validCount = 0; + mq->first = 0; + mq->msgCount = msgCount; + mq->msg = msg; +} diff --git a/lib/ultralib/src/os/createthread.c b/lib/ultralib/src/os/createthread.c new file mode 100644 index 0000000..1ae9f0b --- /dev/null +++ b/lib/ultralib/src/os/createthread.c @@ -0,0 +1,27 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" +#include "osint.h" + +void osCreateThread(OSThread *t, OSId id, void (*entry)(void *), void *arg, void *sp, OSPri p) { + register u32 saveMask; + OSIntMask mask; + t->id = id; + t->priority = p; + t->next = NULL; + t->queue = NULL; + t->context.pc = (u32)entry; + t->context.a0 = (s64)(s32)arg; // Double cast gets rid of compiler warning + t->context.sp = (s64)(s32)sp - 16; + t->context.ra = (u64)__osCleanupThread; + mask = OS_IM_ALL; + t->context.sr = SR_IMASK | SR_EXL | SR_IE; + t->context.rcp = (mask & RCP_IMASK) >> RCP_IMASKSHIFT; + t->context.fpcsr = (u32)(FPCSR_FS | FPCSR_EV); + t->fp = 0; + t->state = OS_STATE_STOPPED; + t->flags = 0; + saveMask = __osDisableInt(); + t->tlnext = __osActiveQueue; + __osActiveQueue = t; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/destroythread.c b/lib/ultralib/src/os/destroythread.c new file mode 100644 index 0000000..43d2436 --- /dev/null +++ b/lib/ultralib/src/os/destroythread.c @@ -0,0 +1,37 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osDestroyThread(OSThread *t) { + register u32 saveMask; + register OSThread *pred; + register OSThread *succ; + + saveMask = __osDisableInt(); + + if (t == NULL) { + t = __osRunningThread; + } else if (t->state != OS_STATE_STOPPED) { + __osDequeueThread(t->queue, t); + } + + if (__osActiveQueue == t) { + __osActiveQueue = __osActiveQueue->tlnext; + } else { + pred = __osActiveQueue; + while (pred->priority != -1) { + succ = pred->tlnext; + if (succ == t) { + pred->tlnext = t->tlnext; + break; + } + pred = succ; + succ = pred->tlnext; + } + } + + if (t == __osRunningThread) { + __osDispatchThread(); + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/exceptasm.h b/lib/ultralib/src/os/exceptasm.h new file mode 100644 index 0000000..48c1234 --- /dev/null +++ b/lib/ultralib/src/os/exceptasm.h @@ -0,0 +1,23 @@ +#ifndef _EXCEPTASM_H +#define _EXCEPTASM_H + +#define MESG(type) (type << 3) + +#define MQ_MTQUEUE 0 +#define MQ_FULLQUEUE 4 +#define MQ_VALIDCOUNT 8 +#define MQ_FIRST 12 +#define MQ_MSGCOUNT 16 +#define MQ_MSG 20 + +#define OS_EVENTSTATE_MESSAGE_QUEUE 0 +#define OS_EVENTSTATE_MESSAGE 4 + +// __osHwInt struct member offsets +#define HWINTR_CALLBACK 0x00 +#define HWINTR_SP 0x04 + +// __osHwInt struct size +#define HWINTR_SIZE 0x8 + +#endif diff --git a/lib/ultralib/src/os/exceptasm.s b/lib/ultralib/src/os/exceptasm.s new file mode 100644 index 0000000..5a0bdcf --- /dev/null +++ b/lib/ultralib/src/os/exceptasm.s @@ -0,0 +1,1019 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" +#include "PR/os.h" +#include "PR/rcp.h" +#include "PR/rdb.h" +#include "exceptasm.h" +#include "threadasm.h" + +#define KMC_CODE_ENTRY 0xBFF00014 +#define KMC_WPORT 0xBFF08000 +#define KMC_STAT 0xBFF08004 + +.rdata + +#define REDISPATCH 0x00 +#define SW1 0x04 +#define SW2 0x08 +#define RCP 0x0c +#define CART 0x10 +#define PRENMI 0x14 +#define IP6_HDLR 0x18 +#define IP7_HDLR 0x1c +#define COUNTER 0x20 + +__osIntOffTable: + .byte REDISPATCH + .byte PRENMI + .byte IP6_HDLR + .byte IP6_HDLR + .byte IP7_HDLR + .byte IP7_HDLR + .byte IP7_HDLR + .byte IP7_HDLR + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte COUNTER + .byte REDISPATCH + .byte SW1 + .byte SW2 + .byte SW2 + .byte RCP + .byte RCP + .byte RCP + .byte RCP + .byte CART + .byte CART + .byte CART + .byte CART + .byte CART + .byte CART + .byte CART + .byte CART + +__osIntTable: + .word redispatch, sw1, sw2, rcp, cart, prenmi, IP6_Hdlr, IP7_Hdlr, counter + +#ifndef _FINALROM +EXPORT(__osCauseTable_pt) + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 + .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +#endif + +.data + +EXPORT(__osHwIntTable) + .word 0, 0 + .word 0, 0 + .word 0, 0 + .word 0, 0 + .word 0, 0 + +EXPORT(__osPiIntTable) + .word 0, 0 + +#ifndef _FINALROM +__osRdb_DbgRead_Ct: + .word 0 + +__osRdb_Mesg: + .word 0 + +__os_Kdebug_Pkt: + .word 0 + +__osPreviousThread: + .word 0 +#endif + +.text + +LEAF(__osExceptionPreamble) + la k0, __osException + jr k0 +END(__osExceptionPreamble) + +#ifndef _FINALROM +LEAF(__ptExceptionPreamble) +.set noreorder + sw k0, -0x10(sp) + b pt_next + lui k0, %hi(__ptException) + nop + nop +pt_next: + addiu k0, %lo(__ptException) + jr k0 + nop +.set reorder +END(__ptExceptionPreamble) + +LEAF(__ptException) +.set noreorder + mfc0 k0, C0_CAUSE + andi k0, k0, 0x7c + bnez k0, pt_not_Int + srl k0, k0, 2 + mfc0 k0, C0_CAUSE + nop + andi k0, k0, CAUSE_IP7 + beqz k0, __osException + nop + j pt_break + nop +pt_not_Int: + sw k1, -8(sp) + /* determine if the pt exception handler should deal with this cause */ + la k1, __osCauseTable_pt + add k1, k1, k0 + lbu k0, (k1) + beqz k0, __osException + nop +pt_break: +pi_ok_loop: + lw k0, PHYS_TO_K1(PI_STATUS_REG) + nop + andi k0, k0, (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY) + bnez k0, pi_ok_loop + nop + lw k0, KMC_STAT + nop + andi k0, k0, 8 + bnez k0, pt_prof + li k0, KMC_CODE_ENTRY + lw k1, -8(sp) + jr k0 + addiu sp, sp, -0x60 +pt_prof: + mfc0 k0, C0_EPC + /* the following two ways is a (necessarily) messy way to write "sw k0, KMC_WPORT" without using at */ + lui k1, (KMC_WPORT >> 16 + 1) + sw k0, -(KMC_WPORT & 0xFFFF)(k1) + lw k1, -8(sp) + lw k0, -0x10(sp) + eret + nop +.set reorder +END(__ptException) +#endif + +LEAF(__osException) + la k0, __osThreadSave + /* save AT */ +.set noat + sd $1, THREAD_GP1(k0); +.set at + /* save sr */ +STAY2(mfc0 k1, C0_SR) + sw k1, THREAD_SR(k0) + /* clear interrupts */ + and k1, k1, -4 +STAY2(mtc0 k1, C0_SR) + /* save other regs */ + sd $8, THREAD_GP8(k0) + sd $9, THREAD_GP9(k0) + sd $10, THREAD_GP10(k0) + /* say fp has not been used */ + sw zero, THREAD_FP(k0) + /* this instruction is useless, leftover because of bad placement of an ifdef for the debug version */ +STAY2(mfc0 t0, C0_CAUSE) +#ifndef _FINALROM + lw t2, __kmc_pt_mode + bnez t2, skip_kmc_mode + andi t1, t0, 0x7c + li t2, 0 + bne t1, t2, savecontext + and t1, k1, t0 + andi t2, t1, CAUSE_IP7 + beqz t2, notIP7 + /* clear rdb write interrupt */ + li t1, RDB_WRITE_INTR_REG + sw zero, (t1) +IP7check: +STAY2(mfc0 t0, C0_CAUSE) + andi t0, t0, CAUSE_IP7 + bne zero, t0, IP7check + lui t2, (RDB_BASE_REG >> 16) + lw t0, (RDB_BASE_REG & 0xFFFF)(t2) + srl t1, t0, 0x1a + andi t1, t1, 0x3f + li t2, RDB_TYPE_HtoG_DATA + beq t1, t2, HandData + li t2, RDB_TYPE_HtoG_DEBUG + beq t1, t2, HandDbg + li t2, RDB_TYPE_HtoG_KDEBUG + beq t1, t2, HandKDebug + li t2, RDB_TYPE_HtoG_DEBUG_CT + beq t1, t2, DbgCnt + li t2, RDB_TYPE_HtoG_DATA_DONE + beq t1, t2, DataRead + li t2, RDB_TYPE_HtoG_LOG_DONE + beq t1, t2, LogRead + li t2, RDB_TYPE_HtoG_REQ_RAMROM + beq t1, t2, ReqRamrom + li t2, RDB_TYPE_HtoG_FREE_RAMROM + beq t1, t2, FreeRamrom + li t2, RDB_TYPE_HtoG_PROF_SIGNAL + beq t1, t2, SignalProf + b rdbout +SignalProf: + li t2, 1 + srl t1, t0, 0x10 + andi t1, t1, 0xff + beq t1, t2, AckProf + li t2, 0xa8 + sw t2, __osRdb_Mesg + b savecontext +AckProf: + li t2, 0xb0 + sw t2, __osRdb_Mesg + b savecontext +HandKDebug: + sw t0, __os_Kdebug_Pkt + b savecontext +DbgCnt: + li t2, 0xffffff + and t1, t0, t2 + sw t1, __osRdb_DbgRead_Ct + b rdbout +DataRead: + li t2, 0x88 + sw t2, __osRdb_Mesg + b savecontext +LogRead: + li t2, 0x80 + sw t2, __osRdb_Mesg + b savecontext +ReqRamrom: + li t2, 0x90 + sw t2, __osRdb_Mesg + b savecontext +FreeRamrom: + li t2, 0x98 + sw t2, __osRdb_Mesg + b savecontext +HandData: + srl t1, t0, 0x18 + andi t1, t1, 3 + beq zero, t1, rdbout + lw t2, __osRdb_Read_Data_Ct + subu t2, t2, t1 + sw t2, __osRdb_Read_Data_Ct + sd t3, THREAD_GP11(k0) + lw t3, __osRdb_Read_Data_Buf + srl t2, t0, 0x10 + andi t2, t2, 0xff + sb t2, (t3) + addi t3, t3, 1 + addi t1, t1, -1 + beq zero, t1, doneData + srl t2, t0, 8 + andi t2, t2, 0xff + sb t2, (t3) + addi t3, t3, 1 + addi t1, t1, -1 + beq zero, t1, doneData + andi t0, t0, 0xff + sb t0, (t3) + addi t3, t3, 1 +doneData: + sw t3, __osRdb_Read_Data_Buf + ld t3, THREAD_GP11(k0) + lw t2, __osRdb_Read_Data_Ct + bne zero, t2, rdbout + li t2, 0x78 + sw t2, __osRdb_Mesg + b savecontext +HandDbg: + srl t1, t0, 0x18 + andi t1, t1, 3 + beq zero, t1, rdbout + lw t2, __osRdb_DbgRead_Ct + subu t2, t2, t1 + sw t2, __osRdb_DbgRead_Ct + sd t3, THREAD_GP11(k0) + lw t3, __osRdb_DbgRead_Buf + bne zero, t3, 1f + ld t3, THREAD_GP11(k0) + b rdbout +1: + srl t2, t0, 0x10 + andi t2, t2, 0xff + sb t2, (t3) + addi t3, t3, 1 + addi t1, t1, -1 + beq zero, t1, doneDbg + srl t2, t0, 8 + andi t2, t2, 0xff + sb t2, (t3) + addi t3, t3, 1 + addi t1, t1, -1 + beq zero, t1, doneDbg + andi t0, t0, 0xff + sb t0, (t3) + addi t3, t3, 1 +doneDbg: + sw t3, __osRdb_DbgRead_Buf + ld t3, THREAD_GP11(k0) + lw t2, __osRdb_DbgRead_Ct + bne zero, t2, rdbout + li t2, 0xa0 + sw t2, __osRdb_Mesg + b savecontext +notIP7: + andi t2, t1, CAUSE_IP6 + beqz t2, savecontext + /* clear rdb read interrupt */ + li t1, RDB_READ_INTR_REG + sw zero, (t1) + lw t2, __osRdb_IP6_Ct + bnez t2, 1f + li t2, 1 + sw t2, __osRdb_IP6_Empty + b rdbout +1: + addi t2, t2, -1 + sw t2, __osRdb_IP6_Ct + lw t0, __osRdb_IP6_Data + lw t1, __osRdb_IP6_CurSend + sll t2, t1, 2 + add t0, t2, t0 + lw t2, (t0) + addi t1, t1, 1 + lw t0, __osRdb_IP6_Size + sub t0, t0, t1 + bgtz t0, 5f + li t1, 0 +5: + sw t1, __osRdb_IP6_CurSend +checkIP6: +STAY2(mfc0 t0, C0_CAUSE) + andi t0, t0, CAUSE_IP6 + bne zero, t0, checkIP6 + lui t0, (RDB_BASE_REG >> 16) + sw t2, (RDB_BASE_REG & 0xFFFF)(t0) +rdbout: + ld t0, THREAD_GP8(k0) + ld t1, THREAD_GP9(k0) + ld t2, THREAD_GP10(k0) +.set noat + ld $1, THREAD_GP1(k0) +.set at + lw k1, THREAD_SR(k0) +STAY2(mtc0 k1, C0_SR) + nop + nop + nop + nop + eret + +skip_kmc_mode: +#endif + +savecontext: + move t0, k0 + lw k0, __osRunningThread +#ifndef _FINALROM + sw k0, __osPreviousThread +#endif + ld t1, THREAD_GP1(t0) + sd t1, THREAD_GP1(k0) + ld t1, THREAD_SR(t0) + sd t1, THREAD_SR(k0) + ld t1, THREAD_GP8(t0) + sd t1, THREAD_GP8(k0) + ld t1, THREAD_GP9(t0) + sd t1, THREAD_GP9(k0) + ld t1, THREAD_GP10(t0) + sd t1, THREAD_GP10(k0) + sd $2, THREAD_GP2(k0) + sd $3, THREAD_GP3(k0) + sd $4, THREAD_GP4(k0) + sd $5, THREAD_GP5(k0) + sd $6, THREAD_GP6(k0) + sd $7, THREAD_GP7(k0) + sd $11, THREAD_GP11(k0) + sd $12, THREAD_GP12(k0) + sd $13, THREAD_GP13(k0) + sd $14, THREAD_GP14(k0) + sd $15, THREAD_GP15(k0) + sd $16, THREAD_GP16(k0) + sd $17, THREAD_GP17(k0) + sd $18, THREAD_GP18(k0) + sd $19, THREAD_GP19(k0) + sd $20, THREAD_GP20(k0) + sd $21, THREAD_GP21(k0) + sd $22, THREAD_GP22(k0) + sd $23, THREAD_GP23(k0) + sd $24, THREAD_GP24(k0) + sd $25, THREAD_GP25(k0) + sd $28, THREAD_GP28(k0) + sd $29, THREAD_GP29(k0) + sd $30, THREAD_GP30(k0) + sd $31, THREAD_GP31(k0) + + mflo t0 + sd t0, THREAD_LO(k0) + mfhi t0 + sd t0, THREAD_HI(k0) + + lw k1, THREAD_SR(k0) + andi t1, k1, SR_IMASK + beqz t1, savercp + +/*if any interrupts are enabled*/ + la t0, __OSGlobalIntMask + lw t0, 0(t0) + xor t2, t0, ~0 /* not except not using not */ + andi t2, t2, SR_IMASK + or ta0, t1, t2 + and t3, k1, ~SR_IMASK + or t3, t3, ta0 + sw t3, THREAD_SR(k0) + andi t0, t0, SR_IMASK + and t1, t1, t0 + and k1, k1, ~SR_IMASK + or k1, k1, t1 +savercp: + + lw t1, PHYS_TO_K1(MI_INTR_MASK_REG) + beqz t1, endrcp + + la t0, __OSGlobalIntMask + lw t0, 0(t0) + + srl t0, t0, 0x10 + xor t0, t0, ~0 + andi t0, t0, 0x3f + lw ta0, THREAD_RCP(k0) + and t0, t0, ta0 + or t1, t1, t0 +endrcp: + sw t1, THREAD_RCP(k0) +STAY2(mfc0 t0, C0_EPC) + sw t0, THREAD_PC(k0) + lw t0, THREAD_FP(k0) + beqz t0, 1f + cfc1 t0, fcr31 + nop + sw t0, THREAD_FPCSR(k0) + sdc1 $f0, THREAD_FP0(k0) + sdc1 $f2, THREAD_FP2(k0) + sdc1 $f4, THREAD_FP4(k0) + sdc1 $f6, THREAD_FP6(k0) + sdc1 $f8, THREAD_FP8(k0) + sdc1 $f10, THREAD_FP10(k0) + sdc1 $f12, THREAD_FP12(k0) + sdc1 $f14, THREAD_FP14(k0) + sdc1 $f16, THREAD_FP16(k0) + sdc1 $f18, THREAD_FP18(k0) + sdc1 $f20, THREAD_FP20(k0) + sdc1 $f22, THREAD_FP22(k0) + sdc1 $f24, THREAD_FP24(k0) + sdc1 $f26, THREAD_FP26(k0) + sdc1 $f28, THREAD_FP28(k0) + sdc1 $f30, THREAD_FP30(k0) +1: +STAY2(mfc0 t0, C0_CAUSE) + sw t0, THREAD_CAUSE(k0) + + li t1, OS_STATE_RUNNABLE + sh t1, THREAD_STATE(k0) + +#ifndef _FINALROM + lw a0, __os_Kdebug_Pkt + beqz a0, no_kdebug + sw zero, __os_Kdebug_Pkt + jal kdebugserver + b __osDispatchThreadSave +no_kdebug: + lw a0, __osRdb_Mesg + beqz a0, no_rdb_mesg + sw zero, __osRdb_Mesg + jal send_mesg + lw t0, 0x120(k0) +no_rdb_mesg: +#endif + + andi t1, t0, CAUSE_EXCMASK + li t2, EXC_BREAK + beq t1, t2, handle_break + + li t2, EXC_CPU + beq t1, t2, handle_CpU + + li t2, EXC_INT + bne t1, t2, panic +handle_interrupt: + and s0, k1, t0 +next_interrupt: + andi t1, s0, SR_IMASK + srl t2, t1, 0xc + bnez t2, 1f + + srl t2, t1, SR_IMASKSHIFT + addi t2, t2, 16 +1: + + lbu t2, __osIntOffTable(t2) + + lw t2, __osIntTable(t2) + jr t2 + +IP6_Hdlr: + and s0, s0, ~CAUSE_IP6 + b next_interrupt + +IP7_Hdlr: + and s0, s0, ~CAUSE_IP7 + b next_interrupt + +counter: +STAY2(mfc0 t1, C0_COMPARE) +STAY2(mtc0 t1, C0_COMPARE) + li a0, MESG(OS_EVENT_COUNTER) + jal send_mesg + and s0, s0, ~CAUSE_IP8 + b next_interrupt + +cart: + and s0, s0, ~CAUSE_IP4 + la t1, __osHwIntTable + add t1, HWINTR_SIZE + lw t2, HWINTR_CALLBACK(t1) + + beqz t2, 1f + + lw sp, HWINTR_SP(t1) + jalr t2 + + beqz v0, 1f + b redispatch + +1: + li a0, MESG(OS_EVENT_CART) + jal send_mesg + b next_interrupt + +rcp: + lw s1, PHYS_TO_K1(MI_INTR_REG) + la t0, __OSGlobalIntMask + lw t0, (t0) + + srl t0, t0, 0x10 + and s1, s1, t0 + andi t1, s1, MI_INTR_SP + beqz t1, vi + + andi s1, s1, 0x3e + lw ta0, PHYS_TO_K1(SP_STATUS_REG) + li t1, (SP_CLR_INTR | SP_CLR_SIG3) + + sw t1, PHYS_TO_K1(SP_STATUS_REG) + andi ta0, ta0, 0x300 + beqz ta0, sp_other_break + + li a0, MESG(OS_EVENT_SP) + jal send_mesg + + beqz s1, NoMoreRcpInts + + b vi + +sp_other_break: + li a0, MESG(OS_EVENT_SP_BREAK) + jal send_mesg + + beqz s1, NoMoreRcpInts + +vi: + andi t1, s1, 0x8 + beqz t1, ai + + andi s1, s1, 0x37 + + sw zero, PHYS_TO_K1(VI_CURRENT_REG) + li a0, MESG(OS_EVENT_VI) + jal send_mesg + beqz s1, NoMoreRcpInts + +ai: + andi t1, s1, 0x4 + beqz t1, si + + andi s1, s1, 0x3b + + li t1, 1 + sw t1, PHYS_TO_K1(AI_STATUS_REG) + + li a0, MESG(OS_EVENT_AI) + jal send_mesg + beqz s1, NoMoreRcpInts + +si: + andi t1, s1, 0x2 + beqz t1, pi + + andi s1, s1, 0x3d + /* any write clears interrupts */ + sw zero, PHYS_TO_K1(SI_STATUS_REG) + li a0, MESG(OS_EVENT_SI) + jal send_mesg + beqz s1, NoMoreRcpInts + +pi: + andi t1, s1, 0x10 + beqz t1, dp + + andi s1, s1, 0x2f + + li t1, PI_STATUS_CLR_INTR + sw t1, PHYS_TO_K1(PI_STATUS_REG) + + la t1, __osPiIntTable + lw t2, (t1) + beqz t2, 1f + + lw sp, 4(t1) + move a0, v0 + jalr t2 + + bnez v0, 2f +1: + li a0, MESG(OS_EVENT_PI) + jal send_mesg +2: + beqz s1, NoMoreRcpInts + +dp: + andi t1, s1, 0x20 + beqz t1, NoMoreRcpInts + + andi s1, s1, 0x1f + + li t1, MI_CLR_DP_INTR + sw t1, PHYS_TO_K1(MI_INIT_MODE_REG) + + li a0, MESG(OS_EVENT_DP) + jal send_mesg + +NoMoreRcpInts: + and s0, s0, ~CAUSE_IP3 + b next_interrupt + +prenmi: + lw k1, THREAD_SR(k0) + + and k1, k1, ~CAUSE_IP5 + sw k1, THREAD_SR(k0) + la t1, __osShutdown + lw t2, 0(t1) + beqz t2, firstnmi + + and s0, s0, ~CAUSE_IP5 + b redispatch + +firstnmi: + li t2, 1 + sw t2, 0(t1) /* __osShutdown */ + li a0, MESG(OS_EVENT_PRENMI) + jal send_mesg + + and s0, s0, ~CAUSE_IP5 + lw t2, __osRunQueue + lw k1, THREAD_SR(t2) + and k1, k1, ~CAUSE_IP5 + sw k1, THREAD_SR(t2) + b redispatch + +sw2: + and t0, t0, ~CAUSE_SW2 +STAY2(mtc0 t0, C0_CAUSE) + + li a0, MESG(OS_EVENT_SW2) + jal send_mesg + + and s0, s0, ~CAUSE_SW2 + b next_interrupt + +sw1: + and t0, t0, ~CAUSE_SW1 +STAY2(mtc0 t0, C0_CAUSE) + + li a0, MESG(OS_EVENT_SW1) + jal send_mesg + + and s0, s0, ~CAUSE_SW1 + b next_interrupt + +handle_break: + li t1, OS_FLAG_CPU_BREAK + sh t1, THREAD_FLAGS(k0) + li a0, MESG(OS_EVENT_CPU_BREAK) + jal send_mesg + b redispatch + +redispatch: + lw t1, THREAD_PRI(k0) + lw t2, __osRunQueue + lw t3, THREAD_PRI(t2) + + bge t1, t3, enqueueRunning + + move a1, k0 + la a0, __osRunQueue + + jal __osEnqueueThread + + j __osDispatchThread + +enqueueRunning: + la t1, __osRunQueue + lw t2, MQ_MTQUEUE(t1) + sw t2, THREAD_NEXT(k0) + sw k0, MQ_MTQUEUE(t1) + j __osDispatchThread +panic: + sw k0, __osFaultedThread + li t1, OS_STATE_STOPPED + sh t1, THREAD_STATE(k0) + li t1, OS_FLAG_FAULT + sh t1, THREAD_FLAGS(k0) + +STAY2(mfc0 t2, C0_BADVADDR) + + sw t2, THREAD_BADVADDR(k0) + + li a0, MESG(OS_EVENT_FAULT) + jal send_mesg + j __osDispatchThread +END(__osException) + +LEAF(send_mesg) + move s2, ra + la t2, __osEventStateTab + addu t2, t2, a0 + lw t1, OS_EVENTSTATE_MESSAGE_QUEUE(t2) + beqz t1, send_done + + lw t3, MQ_VALIDCOUNT(t1) + lw ta0, MQ_MSGCOUNT(t1) + + bge t3, ta0, send_done + + lw ta1, MQ_FIRST(t1) + addu ta1, ta1, t3 + + rem ta1, ta1, ta0 + lw ta0, MQ_MSG(t1) + mul ta1, ta1, 4 + addu ta0, ta0, ta1 + lw ta1, OS_EVENTSTATE_MESSAGE(t2) + sw ta1, 0(ta0) /* msg[ta1] = */ + addiu t2, t3, 1 + sw t2, MQ_VALIDCOUNT(t1) + lw t2, MQ_MTQUEUE(t1) + lw t3, THREAD_NEXT(t2) + beqz t3, send_done + + move a0, t1 + jal __osPopThread + + move t2, v0 + + move a1, t2 + la a0, __osRunQueue + jal __osEnqueueThread +send_done: + jr s2 +END(send_mesg) + +LEAF(handle_CpU) /* coprocessor error */ + and t1, t0, CAUSE_CEMASK + srl t1, t1, CAUSE_CESHIFT + li t2, 1 /* cp1 error */ + bne t1, t2, panic + + /* enable cp1 (fpu) for this thread */ + li t1, 1 + sw t1, THREAD_FP(k0) + lw k1, THREAD_SR(k0) + or k1, k1, SR_CU1 + sw k1, THREAD_SR(k0) + b enqueueRunning +END(handle_CpU) + +LEAF(__osEnqueueAndYield) + lw a1, __osRunningThread +#ifndef _FINALROM + sw a1, __osPreviousThread +#endif +STAY2(mfc0 t0, C0_SR) + ori t0, t0, SR_EXL + sw t0, THREAD_SR(a1) + sd s0, THREAD_GP16(a1) + sd s1, THREAD_GP17(a1) + sd s2, THREAD_GP18(a1) + sd s3, THREAD_GP19(a1) + sd s4, THREAD_GP20(a1) + sd s5, THREAD_GP21(a1) + sd s6, THREAD_GP22(a1) + sd s7, THREAD_GP23(a1) + sd gp, THREAD_GP28(a1) + sd sp, THREAD_GP29(a1) + sd s8, THREAD_GP30(a1) + sd ra, THREAD_GP31(a1) + sw ra, THREAD_PC(a1) + lw k1, THREAD_FP(a1) + beqz k1, 1f + cfc1 k1, fcr31 + sw k1, THREAD_FPCSR(a1) + sdc1 $f20, THREAD_FP20(a1) + sdc1 $f22, THREAD_FP22(a1) + sdc1 $f24, THREAD_FP24(a1) + sdc1 $f26, THREAD_FP26(a1) + sdc1 $f28, THREAD_FP28(a1) + sdc1 $f30, THREAD_FP30(a1) +1: + lw k1, THREAD_SR(a1) + andi t1, k1, SR_IMASK + beqz t1, 2f + + la t0, __OSGlobalIntMask + lw t0, 0(t0) + xor t0, t0, ~0 + andi t0, t0, SR_IMASK + or t1, t1, t0 + and k1, k1, ~SR_IMASK + or k1, k1, t1 + sw k1, THREAD_SR(a1) +2: + lw k1, PHYS_TO_K1(MI_INTR_MASK_REG) + beqz k1, 3f + + la k0, __OSGlobalIntMask + lw k0, 0(k0) + + srl k0, k0, 0x10 + xor k0, k0, ~0 + andi k0, k0, 0x3f + lw t0, THREAD_RCP(a1) + and k0, k0, t0 + or k1, k1, k0 +3: + sw k1, THREAD_RCP(a1) + beqz a0, noEnqueue + jal __osEnqueueThread +noEnqueue: + j __osDispatchThread +END(__osEnqueueAndYield) + +/*__osEnqueueThread(OSThread **, OSThread *)*/ +LEAF(__osEnqueueThread) + move t9, a0 + lw t8, 0(a0) + lw ta3, THREAD_PRI(a1) + lw ta2, THREAD_PRI(t8) + blt ta2, ta3, 1f +2: + move t9, t8 + lw t8, THREAD_NEXT(t8) + lw ta2, THREAD_PRI(t8) + bge ta2, ta3, 2b +1: + lw t8, THREAD_NEXT(t9) + sw t8, THREAD_NEXT(a1) + sw a1, THREAD_NEXT(t9) + sw a0, THREAD_QUEUE(a1) + jr ra +END(__osEnqueueThread) + +LEAF(__osPopThread) + lw v0, 0(a0) /* a0 is OSThread** */ + lw t9, THREAD_NEXT(v0) + sw t9, 0(a0) + jr ra +END(__osPopThread) + +LEAF(__osNop) + jr ra +END(__osNop) + +LEAF(__osDispatchThread) + la a0, __osRunQueue + jal __osPopThread + sw v0, __osRunningThread + li t0, OS_STATE_RUNNING + sh t0, THREAD_STATE(v0) + move k0, v0 + +#ifndef _FINALROM + la t0, __osThprofFunc + lw t0, (t0) + beqz t0, __osDispatchThreadSave + lw a0, __osPreviousThread + lw sp, __osThprofStack + jalr t0 +#endif + +__osDispatchThreadSave: + lw k1, THREAD_SR(k0) + la t0, __OSGlobalIntMask + lw t0, 0(t0) + andi t0, t0, SR_IMASK + andi t1, k1, SR_IMASK + and t1, t1, t0 + and k1, k1, ~SR_IMASK + or k1, k1, t1 +STAY2(mtc0 k1, C0_SR) +.set noat + ld $1, THREAD_GP1(k0) +.set at + ld $2, THREAD_GP2(k0) + ld $3, THREAD_GP3(k0) + ld $4, THREAD_GP4(k0) + ld $5, THREAD_GP5(k0) + ld $6, THREAD_GP6(k0) + ld $7, THREAD_GP7(k0) + ld $8, THREAD_GP8(k0) + ld $9, THREAD_GP9(k0) + ld $10, THREAD_GP10(k0) + ld $11, THREAD_GP11(k0) + ld $12, THREAD_GP12(k0) + ld $13, THREAD_GP13(k0) + ld $14, THREAD_GP14(k0) + ld $15, THREAD_GP15(k0) + ld $16, THREAD_GP16(k0) + ld $17, THREAD_GP17(k0) + ld $18, THREAD_GP18(k0) + ld $19, THREAD_GP19(k0) + ld $20, THREAD_GP20(k0) + ld $21, THREAD_GP21(k0) + ld $22, THREAD_GP22(k0) + ld $23, THREAD_GP23(k0) + ld $24, THREAD_GP24(k0) + ld $25, THREAD_GP25(k0) + ld $28, THREAD_GP28(k0) + ld $29, THREAD_GP29(k0) + ld $30, THREAD_GP30(k0) + ld $31, THREAD_GP31(k0) + ld k1, THREAD_LO(k0) + mtlo k1 + ld k1, THREAD_HI(k0) + mthi k1 + lw k1, THREAD_PC(k0) +STAY2(mtc0 k1, C0_EPC) + lw k1, THREAD_FP(k0) + beqz k1, 1f + + lw k1, THREAD_FPCSR(k0) +STAY2(ctc1 k1, fcr31) + ldc1 $f0, THREAD_FP0(k0) + ldc1 $f2, THREAD_FP2(k0) + ldc1 $f4, THREAD_FP4(k0) + ldc1 $f6, THREAD_FP6(k0) + ldc1 $f8, THREAD_FP8(k0) + ldc1 $f10, THREAD_FP10(k0) + ldc1 $f12, THREAD_FP12(k0) + ldc1 $f14, THREAD_FP14(k0) + ldc1 $f16, THREAD_FP16(k0) + ldc1 $f18, THREAD_FP18(k0) + ldc1 $f20, THREAD_FP20(k0) + ldc1 $f22, THREAD_FP22(k0) + ldc1 $f24, THREAD_FP24(k0) + ldc1 $f26, THREAD_FP26(k0) + ldc1 $f28, THREAD_FP28(k0) + ldc1 $f30, THREAD_FP30(k0) + +1: + lw k1, THREAD_RCP(k0) + la k0, __OSGlobalIntMask + lw k0, 0(k0) + srl k0, k0, 0x10 + and k1, k1, k0 + sll k1, k1, 0x1 + la k0, __osRcpImTable + addu k1, k1, k0 + lhu k1, 0(k1) + la k0, PHYS_TO_K1(MI_INTR_MASK_REG) + sw k1, 0(k0) + + nop + nop + nop + nop + eret +END(__osDispatchThread) + +LEAF(__osCleanupThread) + move a0, zero + nop + jal osDestroyThread +END(__osCleanupThread) diff --git a/lib/ultralib/src/os/exit.c b/lib/ultralib/src/os/exit.c new file mode 100644 index 0000000..d5e60eb --- /dev/null +++ b/lib/ultralib/src/os/exit.c @@ -0,0 +1,8 @@ +#include "PR/os_internal.h" + +void osExit() { + __osGIOInterrupt(16); + + for (;;); +} + diff --git a/lib/ultralib/src/os/getactivequeue.c b/lib/ultralib/src/os/getactivequeue.c new file mode 100644 index 0000000..4175e7d --- /dev/null +++ b/lib/ultralib/src/os/getactivequeue.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSThread *__osGetActiveQueue(void) { + return __osActiveQueue; +} diff --git a/lib/ultralib/src/os/getcause.s b/lib/ultralib/src/os/getcause.s new file mode 100644 index 0000000..873464f --- /dev/null +++ b/lib/ultralib/src/os/getcause.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetCause) + STAY2(mfc0 v0, C0_CAUSE) + jr ra +END(__osGetCause) diff --git a/lib/ultralib/src/os/getcompare.s b/lib/ultralib/src/os/getcompare.s new file mode 100644 index 0000000..99c1758 --- /dev/null +++ b/lib/ultralib/src/os/getcompare.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetCompare) + STAY2(mfc0 v0, C0_COMPARE) + jr ra +END(__osGetCompare) diff --git a/lib/ultralib/src/os/getconfig.s b/lib/ultralib/src/os/getconfig.s new file mode 100644 index 0000000..8165178 --- /dev/null +++ b/lib/ultralib/src/os/getconfig.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetConfig) + STAY2(mfc0 v0, C0_CONFIG) + jr ra +END(__osGetConfig) diff --git a/lib/ultralib/src/os/getcount.s b/lib/ultralib/src/os/getcount.s new file mode 100644 index 0000000..28d5a79 --- /dev/null +++ b/lib/ultralib/src/os/getcount.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(osGetCount) + STAY2(mfc0 v0, C0_COUNT) + jr ra +END(osGetCount) diff --git a/lib/ultralib/src/os/getcurrfaultthread.c b/lib/ultralib/src/os/getcurrfaultthread.c new file mode 100644 index 0000000..7500928 --- /dev/null +++ b/lib/ultralib/src/os/getcurrfaultthread.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSThread *__osGetCurrFaultedThread() { + return __osFaultedThread; +} diff --git a/lib/ultralib/src/os/getfpccsr.s b/lib/ultralib/src/os/getfpccsr.s new file mode 100644 index 0000000..05bb19d --- /dev/null +++ b/lib/ultralib/src/os/getfpccsr.s @@ -0,0 +1,10 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetFpcCsr) + STAY2(cfc1 v0, fcr31) + jr ra +END(__osGetFpcCsr) +.globl __osGetSR diff --git a/lib/ultralib/src/os/gethwinterrupt.c b/lib/ultralib/src/os/gethwinterrupt.c new file mode 100644 index 0000000..3a0e136 --- /dev/null +++ b/lib/ultralib/src/os/gethwinterrupt.c @@ -0,0 +1,13 @@ +#include "PR/os_internal.h" + +struct __osHwInt { + s32 (*handler)(void); + void *stackEnd; +}; + +extern struct __osHwInt __osHwIntTable[]; + +void __osGetHWIntrRoutine(OSHWIntr interrupt, s32 (**handler)(void), void **stackEnd) { + *handler = __osHwIntTable[interrupt].handler; + *stackEnd = __osHwIntTable[interrupt].stackEnd; +} diff --git a/lib/ultralib/src/os/getintmask.s b/lib/ultralib/src/os/getintmask.s new file mode 100644 index 0000000..deaccb6 --- /dev/null +++ b/lib/ultralib/src/os/getintmask.s @@ -0,0 +1,32 @@ +#include "PR/R4300.h" +#include "PR/rcp.h" +#include "PR/os.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osGetIntMask) + mfc0 v0, C0_SR + andi v0, v0, OS_IM_CPU + la t0, __OSGlobalIntMask + lw t1, 0(t0) + xor t0, t1, -1 + andi t0, t0, SR_IMASK + or v0, v0, t0 + + lw t1, PHYS_TO_K1(MI_INTR_MASK_REG) + beqz t1, 1f + + la t0, __OSGlobalIntMask #this is intentionally a macro in the branch delay slot + + lw t0, 0(t0) + srl t0, t0, 0x10 + xor t0, t0, -1 + andi t0, t0, 0x3f + or t1, t1, t0 +1: + sll t2, t1, 0x10 + or v0, v0, t2 + jr ra +END(osGetIntMask) diff --git a/lib/ultralib/src/os/getmemsize.c b/lib/ultralib/src/os/getmemsize.c new file mode 100644 index 0000000..44fbc19 --- /dev/null +++ b/lib/ultralib/src/os/getmemsize.c @@ -0,0 +1,35 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "PR/R4300.h" + +#define STEP 0x100000 +#define SIZE_4MB 0x400000 +#define SIZE_8MB 0x800000 + +u32 osGetMemSize(void) { + vu32* ptr; + u32 size = SIZE_4MB; + u32 data0; + u32 data1; + + while (size < SIZE_8MB) { + ptr = (vu32*)(K1BASE + size); + + data0 = *ptr; + data1 = ptr[STEP / 4 - 1]; + + *ptr ^= ~0; + ptr[STEP / 4 - 1] ^= ~0; + + if ((*ptr != (data0 ^ ~0)) || (ptr[STEP / 4 - 1] != (data1 ^ ~0))) { + return size; + } + + *ptr = data0; + ptr[STEP / 4 - 1] = data1; + + size += STEP; + } + + return size; +} diff --git a/lib/ultralib/src/os/getnextfaultthread.c b/lib/ultralib/src/os/getnextfaultthread.c new file mode 100644 index 0000000..9add6dd --- /dev/null +++ b/lib/ultralib/src/os/getnextfaultthread.c @@ -0,0 +1,28 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSThread *__osGetNextFaultedThread(OSThread *lastFault) { + register int saveMask = __osDisableInt(); + register OSThread *fault; + + if (lastFault == NULL) { + fault = __osActiveQueue; + } else { + fault = lastFault; + } + + while (fault->priority != -1) { + if ((fault->flags & OS_FLAG_FAULT) != 0 && fault != lastFault) { + break; + } + fault = fault->tlnext; + } + + if (fault->priority == -1) { + fault = NULL; + } + + __osRestoreInt(saveMask); + return fault; +} + diff --git a/lib/ultralib/src/os/getsr.s b/lib/ultralib/src/os/getsr.s new file mode 100644 index 0000000..bc9c767 --- /dev/null +++ b/lib/ultralib/src/os/getsr.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetSR) + STAY2(mfc0 v0, C0_SR) + jr ra +END(__osGetSR) diff --git a/lib/ultralib/src/os/getthreadid.c b/lib/ultralib/src/os/getthreadid.c new file mode 100644 index 0000000..9aac16d --- /dev/null +++ b/lib/ultralib/src/os/getthreadid.c @@ -0,0 +1,10 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSId osGetThreadId(OSThread *thread) { + if (thread == NULL) { + thread = __osRunningThread; + } + + return thread->id; +} diff --git a/lib/ultralib/src/os/getthreadpri.c b/lib/ultralib/src/os/getthreadpri.c new file mode 100644 index 0000000..a1e9ce2 --- /dev/null +++ b/lib/ultralib/src/os/getthreadpri.c @@ -0,0 +1,10 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSPri osGetThreadPri(OSThread *thread) { + if (thread == NULL) { + thread = __osRunningThread; + } + + return thread->priority; +} diff --git a/lib/ultralib/src/os/gettime.c b/lib/ultralib/src/os/gettime.c new file mode 100644 index 0000000..aee799a --- /dev/null +++ b/lib/ultralib/src/os/gettime.c @@ -0,0 +1,15 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSTime osGetTime() { + u32 tmptime; + u32 elapseCount; + OSTime currentCount; + register u32 saveMask; + saveMask = __osDisableInt(); + tmptime = osGetCount(); + elapseCount = tmptime - __osBaseCounter; + currentCount = __osCurrentTime; + __osRestoreInt(saveMask); + return currentCount + elapseCount; +} diff --git a/lib/ultralib/src/os/gettlbasid.s b/lib/ultralib/src/os/gettlbasid.s new file mode 100644 index 0000000..a0702ea --- /dev/null +++ b/lib/ultralib/src/os/gettlbasid.s @@ -0,0 +1,11 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.set noreorder +.text +LEAF(__osGetTLBASID) + mfc0 v0, C0_ENTRYHI + jr ra + nop +END(__osGetTLBASID) diff --git a/lib/ultralib/src/os/gettlbhi.s b/lib/ultralib/src/os/gettlbhi.s new file mode 100644 index 0000000..04c03e9 --- /dev/null +++ b/lib/ultralib/src/os/gettlbhi.s @@ -0,0 +1,17 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.set noreorder +.text +LEAF(__osGetTLBHi) + mtc0 a0, C0_INX + nop + tlbr + nop + nop + nop + mfc0 v0, C0_ENTRYHI + jr ra + nop +END(__osGetTLBHi) diff --git a/lib/ultralib/src/os/gettlblo0.s b/lib/ultralib/src/os/gettlblo0.s new file mode 100644 index 0000000..3b2c2ec --- /dev/null +++ b/lib/ultralib/src/os/gettlblo0.s @@ -0,0 +1,17 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.set noreorder +.text +LEAF(__osGetTLBLo0) + mtc0 a0, C0_INX + nop + tlbr + nop + nop + nop + mfc0 v0, C0_ENTRYLO0 + jr ra + nop +END(__osGetTLBLo0) diff --git a/lib/ultralib/src/os/gettlblo1.s b/lib/ultralib/src/os/gettlblo1.s new file mode 100644 index 0000000..a24baef --- /dev/null +++ b/lib/ultralib/src/os/gettlblo1.s @@ -0,0 +1,17 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.set noreorder +.text +LEAF(__osGetTLBLo1) + mtc0 a0, C0_INX + nop + tlbr + nop + nop + nop + mfc0 v0, C0_ENTRYLO1 + jr ra + nop +END(__osGetTLBLo1) diff --git a/lib/ultralib/src/os/gettlbpagemask.s b/lib/ultralib/src/os/gettlbpagemask.s new file mode 100644 index 0000000..de9954a --- /dev/null +++ b/lib/ultralib/src/os/gettlbpagemask.s @@ -0,0 +1,17 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.set noreorder +.text +LEAF(__osGetTLBPageMask) + mtc0 a0, C0_INX + nop + tlbr + nop + nop + nop + mfc0 v0, C0_PAGEMASK + jr ra + nop +END(__osGetTLBPageMask) diff --git a/lib/ultralib/src/os/getwatchlo.s b/lib/ultralib/src/os/getwatchlo.s new file mode 100644 index 0000000..4eee9ee --- /dev/null +++ b/lib/ultralib/src/os/getwatchlo.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osGetWatchLo) + STAY2(mfc0 v0, C0_WATCHLO) + jr ra +END(__osGetWatchLo) diff --git a/lib/ultralib/src/os/initialize.c b/lib/ultralib/src/os/initialize.c new file mode 100644 index 0000000..ecc001e --- /dev/null +++ b/lib/ultralib/src/os/initialize.c @@ -0,0 +1,105 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" + +typedef struct +{ + /* 0x0 */ unsigned int inst1; + /* 0x4 */ unsigned int inst2; + /* 0x8 */ unsigned int inst3; + /* 0xC */ unsigned int inst4; +} __osExceptionVector; +extern __osExceptionVector __osExceptionPreamble; + +extern OSPiHandle __Dom1SpeedParam; +extern OSPiHandle __Dom2SpeedParam; + +OSTime osClockRate = OS_CLOCK_RATE; +s32 osViClock = VI_NTSC_CLOCK; +u32 __osShutdown = 0; +u32 __OSGlobalIntMask = OS_IM_ALL; +#ifdef _FINALROM +u32 __osFinalrom; +#else +void* __printfunc = NULL; +u32 __kmc_pt_mode; +#endif + +void __createSpeedParam(void) { + __Dom1SpeedParam.type = DEVICE_TYPE_INIT; + __Dom1SpeedParam.latency = IO_READ(PI_BSD_DOM1_LAT_REG); + __Dom1SpeedParam.pulse = IO_READ(PI_BSD_DOM1_PWD_REG); + __Dom1SpeedParam.pageSize = IO_READ(PI_BSD_DOM1_PGS_REG); + __Dom1SpeedParam.relDuration = IO_READ(PI_BSD_DOM1_RLS_REG); + + __Dom2SpeedParam.type = DEVICE_TYPE_INIT; + __Dom2SpeedParam.latency = IO_READ(PI_BSD_DOM2_LAT_REG); + __Dom2SpeedParam.pulse = IO_READ(PI_BSD_DOM2_PWD_REG); + __Dom2SpeedParam.pageSize = IO_READ(PI_BSD_DOM2_PGS_REG); + __Dom2SpeedParam.relDuration = IO_READ(PI_BSD_DOM2_RLS_REG); +} + +void __osInitialize_common() { + u32 pifdata; + +#ifdef _FINALROM + __osFinalrom = TRUE; +#endif + + __osSetSR(__osGetSR() | SR_CU1); //enable fpu + __osSetFpcCsr(FPCSR_FS | FPCSR_EV); //flush denorm to zero, enable invalid operation + __osSetWatchLo(0x4900000); + + while (__osSiRawReadIo(PIF_RAM_END - 3, &pifdata)) { //last byte of joychannel ram + ; + } + while (__osSiRawWriteIo(PIF_RAM_END - 3, pifdata | 8)) { + ; //todo: magic contant + } + *(__osExceptionVector *)UT_VEC = __osExceptionPreamble; + *(__osExceptionVector *)XUT_VEC = __osExceptionPreamble; + *(__osExceptionVector *)ECC_VEC = __osExceptionPreamble; + *(__osExceptionVector *)E_VEC = __osExceptionPreamble; + osWritebackDCache((void *)UT_VEC, E_VEC - UT_VEC + sizeof(__osExceptionVector)); + osInvalICache((void *)UT_VEC, E_VEC - UT_VEC + sizeof(__osExceptionVector)); + __createSpeedParam(); + osUnmapTLBAll(); + osMapTLBRdb(); + osClockRate = osClockRate * 3 / 4; + + if (osResetType == 0 ) { // cold reset + bzero(osAppNMIBuffer, OS_APP_NMI_BUFSIZE); + } + + if (osTvType == OS_TV_PAL) { + osViClock = VI_PAL_CLOCK; + } else if (osTvType == OS_TV_MPAL) { + osViClock = VI_MPAL_CLOCK; + } else { + osViClock = VI_NTSC_CLOCK; + } + + // Wait until there are no RCP interrupts + if (__osGetCause() & CAUSE_IP5) { + while (TRUE) { + ; + } + } + + IO_WRITE(AI_CONTROL_REG, AI_CONTROL_DMA_ON); + IO_WRITE(AI_DACRATE_REG, AI_MAX_DAC_RATE - 1); + IO_WRITE(AI_BITRATE_REG, AI_MAX_BIT_RATE - 1); +} + +void __osInitialize_autodetect() { +#ifndef _FINALROM + if (__checkHardware_msp()) { + __osInitialize_msp(); + } else if (__checkHardware_kmc()) { + __osInitialize_kmc(); + } else if (__checkHardware_isv()) { + __osInitialize_isv(); + } else { + __osInitialize_emu(); + } +#endif +} diff --git a/lib/ultralib/src/os/initialize_emu.c b/lib/ultralib/src/os/initialize_emu.c new file mode 100644 index 0000000..5b68da5 --- /dev/null +++ b/lib/ultralib/src/os/initialize_emu.c @@ -0,0 +1,28 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rdb.h" +#include "osint.h" + +typedef struct +{ + /* 0x0 */ unsigned int inst1; + /* 0x4 */ unsigned int inst2; + /* 0x8 */ unsigned int inst3; + /* 0xC */ unsigned int inst4; +} __osExceptionVector; + +static void* proutSyncPrintf(void* str, const char* buf, size_t n) { + size_t sent = 0; + + while (sent < n) { + sent += __osRdbSend(buf + sent, n - sent, RDB_TYPE_GtoH_PRINT); + } + return 1; +} + +void __osInitialize_emu(void) { + __printfunc = proutSyncPrintf; +} + +#endif diff --git a/lib/ultralib/src/os/initialize_isv.c b/lib/ultralib/src/os/initialize_isv.c new file mode 100644 index 0000000..cd64821 --- /dev/null +++ b/lib/ultralib/src/os/initialize_isv.c @@ -0,0 +1,176 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "osint.h" + +#include "macros.h" + +typedef struct +{ + /* 0x0 */ unsigned int inst1; + /* 0x4 */ unsigned int inst2; + /* 0x8 */ unsigned int inst3; + /* 0xC */ unsigned int inst4; +} __osExceptionVector; + +extern __osExceptionVector __isExpJP; + +void MonitorInitBreak(void); + +typedef struct { + /* 0x00 */ u32 magic; // IS64 + /* 0x04 */ u32 get; + /* 0x08 */ u8 unk_08[0x14-0x08]; + /* 0x14 */ u32 put; + /* 0x18 */ u8 unk_18[0x20-0x18]; + /* 0x20 */ u8 data[0x10000-0x20]; +} ISVDbg; + +#define IS64_MAGIC 'IS64' + +ISVDbg* gISVDbgPrnAdrs; + +u32 leoComuBuffAdd; +u32 gISVFlag; +u16 gISVChk; + +__osExceptionVector ramOldVector ALIGNED(8); + +static OSPiHandle* is_Handle; + +void isPrintfInit(void) { + is_Handle = osCartRomInit(); + + osEPiWriteIo(is_Handle, &gISVDbgPrnAdrs->put, 0); + osEPiWriteIo(is_Handle, &gISVDbgPrnAdrs->get, 0); + osEPiWriteIo(is_Handle, gISVDbgPrnAdrs, IS64_MAGIC); +} + +static void* is_proutSyncPrintf(void* arg, const u8* str, u32 count) { + u32 data; + s32 p; + s32 start; + s32 end; + + if (gISVDbgPrnAdrs == NULL) { + return 0; + } + + osEPiReadIo(is_Handle, (u32)&gISVDbgPrnAdrs->magic, &data); + if (data != IS64_MAGIC) { + return 1; + } + osEPiReadIo(is_Handle, (u32)&gISVDbgPrnAdrs->get, &data); + p = data; + osEPiReadIo(is_Handle, (u32)&gISVDbgPrnAdrs->put, &data); + + start = data; + end = start + count; + + if (end >= 0xffe0) { + end -= 0xffe0; + if (p < end || start < p) { + return 1; + } + } else { + if (start < p && p < end) { + return 1; + } + } + while (count) { + if (*str != '\0') { + s32 shift = start & 3; + u32 addr = (u32)&gISVDbgPrnAdrs->data[start & 0xFFFFFFC]; + + shift = (3 - shift) * 8; + + osEPiReadIo(is_Handle, addr, &data); + osEPiWriteIo(is_Handle, addr, (data & ~(0xff << shift)) | (*str << shift)); + + start++; + if (start >= 0xffe0) { + start -= 0xffe0; + } + } + count--; + str++; + } + osEPiWriteIo(is_Handle, (u32)&gISVDbgPrnAdrs->put, start); + + return 1; +} + +int __checkHardware_isv(void) { + u32 i = 0; + u32 data; // BUG: data is used uninitialized + u32 save[4]; + u32 addr; + OSPiHandle* hnd = osCartRomInit(); + + gISVDbgPrnAdrs = NULL; + leoComuBuffAdd = 0; + gISVFlag = IS64_MAGIC; + gISVChk = 0; + + for (i = 0; i < 4; i++) { + osEPiReadIo(hnd, 0xB0000100 + i * 4, save + i); + } + + // data = 0; + osEPiWriteIo(hnd, 0xB000010C, data); + data = IS64_MAGIC; + osEPiWriteIo(hnd, 0xB0000100, IS64_MAGIC); + + for (i = 0; i <= 0x1FFFF; i++) { + osEPiReadIo(hnd, 0xB000010C, &data); + if (data == IS64_MAGIC) { + data = 0; + osEPiWriteIo(hnd, 0xB0000100, data); + gISVChk |= 1; + osEPiReadIo(hnd, 0xB0000104, (void*)&gISVDbgPrnAdrs); + osEPiReadIo(hnd, 0xB0000108, &leoComuBuffAdd); + break; + } + } + + for (i = 0; i < 4; i++) { + osEPiWriteIo(hnd, 0xB0000100 + i * 4, save[i]); + } + + osEPiReadIo(hnd, 0xBFF00000, &data); + + gISVChk |= ((data == IS64_MAGIC) ? 2 : 0); + + return (gISVChk != 0) ? TRUE : FALSE; +} + +void __osInitialize_isv(void) { + void (*fn)(void); + OSPiHandle* hnd; + + if (gISVFlag == IS64_MAGIC || __checkHardware_isv()) { + if (gISVDbgPrnAdrs != NULL) { + __printfunc = is_proutSyncPrintf; + isPrintfInit(); + } + if (gISVChk & 2) { + hnd = osCartRomInit(); + + ramOldVector = *(__osExceptionVector*)E_VEC; + *(__osExceptionVector*)E_VEC = __isExpJP; + + osWritebackDCache(&ramOldVector, 0x10); + osInvalICache(&ramOldVector, 0x10); + osWritebackDCache(0x80000000, 0x190); + osInvalICache(0x80000000, 0x190); + osEPiReadIo(hnd, 0xBFF00010, &fn); + fn(); + } + if (gISVChk & 2) { + MonitorInitBreak(); + } + } +} + +#endif diff --git a/lib/ultralib/src/os/initialize_kmc.c b/lib/ultralib/src/os/initialize_kmc.c new file mode 100644 index 0000000..c09b1fa --- /dev/null +++ b/lib/ultralib/src/os/initialize_kmc.c @@ -0,0 +1,154 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "osint.h" + +typedef struct +{ + /* 0x0 */ unsigned int inst1; + /* 0x4 */ unsigned int inst2; + /* 0x8 */ unsigned int inst3; + /* 0xC */ unsigned int inst4; +} __osExceptionVector; + +extern __osExceptionVector* __ptExceptionPreamble; + +static volatile unsigned int* stat = (unsigned*)0xbff08004; +static volatile unsigned int* wport = (unsigned*)0xbff08000; +static volatile unsigned int* piok = (unsigned*)PHYS_TO_K1(PI_STATUS_REG); + +static void rmonPutchar(char c) { + u32 data; + + while (TRUE) { + osPiReadIo(stat, &data); + if (data & 4) { + osPiWriteIo(wport, c); + break; + } + } +} + +static void* kmc_proutSyncPrintf(void* str, const char* buf, int n) { + int i; + char c; + char* p; + char* q; + char xbuf[128]; + static int column = 0; + + p = &xbuf; + + for (i = 0; i < n; i++) { + c = *buf++; + + switch (c) { + case '\n': + *p++ = '\n'; + column = 0; + break; + case '\t': + do { + *p++ = ' '; + } while (++column % 8); + break; + default: + column++; + *p++ = c; + break; + + } + + if (c == '\n' || (p - xbuf) > 100) { + rmonPutchar((p - xbuf) - 1); + + q = xbuf; + while (q != p) { + rmonPutchar(*q++); + } + p = xbuf; + } + } + if (p != xbuf) { + rmonPutchar((p - xbuf) - 1); + + q = xbuf; + while (q != p) { + rmonPutchar(*q++); + } + } + return (void*)1; +} + +extern u32 __kmc_pt_mode; + +void __osInitialize_kmc(void) { + if (!__kmc_pt_mode) { + int (*fnc)(); + unsigned int* src; + unsigned int* dst; + unsigned int monadr; + volatile unsigned int* mon; + volatile unsigned int* stat; + + stat = (unsigned*)0xbff08004; + mon = (unsigned*)0xBFF00000; + if (*mon != 0x4B4D4300) { + return; + } + + src = (unsigned*)&__ptExceptionPreamble; + dst = (unsigned*)E_VEC; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src+=2; + dst+=2; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + + osWritebackDCache(E_VEC, 0x24); + osInvalICache(E_VEC, 0x24); + + __kmc_pt_mode = TRUE; + + if ((*stat & 0x10) == 0) { + monadr = *(mon + 1); + if (monadr != 0xBFF00000) { + unsigned int* src; + unsigned int* dst = monadr | 0x20000000; + unsigned int ct = 0x2000 / 4; + + src = 0xBFF00000; + + while (ct != 0) { + *dst++ = *src++; + ct--; + } + } + fnc = monadr + 8; + fnc(0x4B4D4300, 0); + } + __printfunc = kmc_proutSyncPrintf; + } +} + +int __checkHardware_kmc(void) { + volatile unsigned int* mon = (unsigned*)0xBFF00000; + + if (*mon == 0x4B4D4300) { + mon = (unsigned*)0xBFF00010; + + if (*mon == 0xB0FFB000) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +#endif diff --git a/lib/ultralib/src/os/initialize_msp.c b/lib/ultralib/src/os/initialize_msp.c new file mode 100644 index 0000000..d0deead --- /dev/null +++ b/lib/ultralib/src/os/initialize_msp.c @@ -0,0 +1,154 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "osint.h" + +typedef struct +{ + /* 0x0 */ unsigned int inst1; + /* 0x4 */ unsigned int inst2; + /* 0x8 */ unsigned int inst3; + /* 0xC */ unsigned int inst4; +} __osExceptionVector; + +extern __osExceptionVector* __ptExceptionPreamble; + +static volatile unsigned int* stat = (unsigned*)0xbff08004; +static volatile unsigned int* wport = (unsigned*)0xbff08000; +static volatile unsigned int* piok = (unsigned*)PHYS_TO_K1(PI_STATUS_REG); + +static void rmonPutchar(char c) { + u32 data; + + while (TRUE) { + osPiReadIo(stat, &data); + if (data & 4) { + osPiWriteIo(wport, c); + break; + } + } +} + +static void* msp_proutSyncPrintf(void* str, const char* buf, int n) { + int i; + char c; + char* p; + char* q; + char xbuf[128]; + static int column = 0; + + p = &xbuf; + + for (i = 0; i < n; i++) { + c = *buf++; + + switch (c) { + case '\n': + *p++ = '\n'; + column = 0; + break; + case '\t': + do { + *p++ = ' '; + } while (++column % 8); + break; + default: + column++; + *p++ = c; + break; + + } + + if (c == '\n' || (p - xbuf) > 100) { + rmonPutchar((p - xbuf) - 1); + + q = xbuf; + while (q != p) { + rmonPutchar(*q++); + } + p = xbuf; + } + } + if (p != xbuf) { + rmonPutchar((p - xbuf) - 1); + + q = xbuf; + while (q != p) { + rmonPutchar(*q++); + } + } + return (void*)1; +} + +extern u32 __kmc_pt_mode; + +void __osInitialize_msp(void) { + if (!__kmc_pt_mode) { + int (*fnc)(); + unsigned int* src; + unsigned int* dst; + unsigned int monadr; + volatile unsigned int* mon; + volatile unsigned int* stat; + + stat = (unsigned*)0xbff08004; + mon = (unsigned*)0xBFF00000; + if (*mon != 0x4B4D4300) { + return; + } + + src = (unsigned*)&__ptExceptionPreamble; + dst = (unsigned*)E_VEC; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src+=2; + dst+=2; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + + osWritebackDCache(E_VEC, 0x24); + osInvalICache(E_VEC, 0x24); + + __kmc_pt_mode = TRUE; + + if ((*stat & 0x10) == 0) { + monadr = *(mon + 1); + if (monadr != 0xBFF00000) { + unsigned int* src; + unsigned int* dst = monadr | 0x20000000; + unsigned int ct = 0x2000 / 4; + + src = 0xBFF00000; + + while (ct != 0) { + *dst++ = *src++; + ct--; + } + } + fnc = monadr + 8; + fnc(0x4B4D4300, 0); + } + __printfunc = msp_proutSyncPrintf; + } +} + +int __checkHardware_msp(void) { + volatile unsigned int* mon = (unsigned*)0xBFF00000; + + if (*mon == 0x4B4D4300) { + mon = (unsigned*)0xBFF00010; + + if (*mon == 0) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +#endif diff --git a/lib/ultralib/src/os/initrdb.c b/lib/ultralib/src/os/initrdb.c new file mode 100644 index 0000000..a332c29 --- /dev/null +++ b/lib/ultralib/src/os/initrdb.c @@ -0,0 +1,30 @@ +#ifndef _FINALROM +#include "PR/os_internal.h" + +void* __osRdb_IP6_Data; +u32 __osRdb_IP6_Size; +u32 __osRdb_IP6_Ct; +u32 __osRdb_IP6_CurWrite; +u32 __osRdb_IP6_CurSend; + +void osInitRdb(u8* sendBuf, u32 sendSize) { + u32 mask; + + sendSize /= 4; + + if (((u32)sendBuf & 3) != 0) { + sendBuf = ((u32)sendBuf & 3) + 4; + sendSize--; + } + mask = __osDisableInt(); + + __osRdb_IP6_Data = sendBuf; + __osRdb_IP6_Size = sendSize; + __osRdb_IP6_Ct = 0; + __osRdb_IP6_CurWrite = 0; + __osRdb_IP6_CurSend = 0; + + __osRestoreInt(mask); +} + +#endif diff --git a/lib/ultralib/src/os/interrupt.s b/lib/ultralib/src/os/interrupt.s new file mode 100644 index 0000000..8fac481 --- /dev/null +++ b/lib/ultralib/src/os/interrupt.s @@ -0,0 +1,41 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(__osDisableInt) + la t2, __OSGlobalIntMask + lw t3, (t2) + andi t3, 0xFF00 + mfc0 t0, C0_SR + and t1, t0, ~SR_IE + mtc0 t1, C0_SR + andi v0, t0, SR_IE + lw t0, (t2) + andi t0, 0xFF00 + beq t0, t3, No_Change_Global_Int + la t2, __osRunningThread + lw t1, 280(t2) + andi t2, t1, 0xFF00 + and t2, t0 + and t1, 0xFFFF00FF + or t1, t2 + and t1, -2 + mtc0 t1, $12 + nop + nop +No_Change_Global_Int: + jr ra + nop +END(__osDisableInt) + +LEAF(__osRestoreInt) + mfc0 t0, C0_SR + or t0, t0, a0 + mtc0 t0, C0_SR + nop + nop + jr ra + nop +END(__osRestoreInt) diff --git a/lib/ultralib/src/os/invaldcache.s b/lib/ultralib/src/os/invaldcache.s new file mode 100644 index 0000000..24cfb1c --- /dev/null +++ b/lib/ultralib/src/os/invaldcache.s @@ -0,0 +1,61 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osInvalDCache) + blez a1, 3f + nop + li t3, DCACHE_SIZE + bgeu a1, t3, 4f + nop + + move t0, a0 + addu t1, a0, a1 + bgeu t0, t1, 3f + nop + + addiu t1, t1, -DCACHE_LINESIZE + andi t2, t0, DCACHE_LINEMASK + beqz t2, 1f + nop + + subu t0, t0, t2 + CACHE((C_HWBINV|CACH_PD), (t0)) + bgeu t0, t1, 3f + # nop + + addiu t0, t0, DCACHE_LINESIZE +1: + andi t2, t1, DCACHE_LINEMASK + beqz t2, 2f + # nop + subu t1, t1, t2 + CACHE((C_HWBINV|CACH_PD), 0x10(t1)) + bltu t1, t0, 3f + # nop +2: + CACHE((C_HINV|CACH_PD), (t0)) + .set noreorder + bltu t0, t1, 2b + addiu t0, t0, DCACHE_LINESIZE + .set reorder +3: + jr ra + # nop +4: + li t0, KUSIZE + addu t1, t0, t3 + addiu t1, t1, -DCACHE_LINESIZE +5: + CACHE((C_IINV|CACH_PD), (t0)) + .set noreorder + bltu t0, t1, 5b + addiu t0, t0, DCACHE_LINESIZE + .set reorder + + jr ra + # nop + # nop +END(osInvalDCache) diff --git a/lib/ultralib/src/os/invalicache.s b/lib/ultralib/src/os/invalicache.s new file mode 100644 index 0000000..aeaf200 --- /dev/null +++ b/lib/ultralib/src/os/invalicache.s @@ -0,0 +1,42 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osInvalICache) + blez a1, 2f + nop + li t3, ICACHE_SIZE + bgeu a1, t3, 3f + nop + move t0, a0 + addu t1, a0, a1 + bgeu t0, t1, 2f + nop + addiu t1, t1, -ICACHE_LINESIZE + andi t2, t0, ICACHE_LINEMASK + subu t0, t0, t2 +1: + CACHE((C_HINV|CACH_PI), (t0)) + .set noreorder + bltu t0, t1, 1b + addiu t0, t0, ICACHE_LINESIZE + .set reorder +2: + jr ra + #nop +3: + li t0, KUSIZE + addu t1, t0, t3 + addiu t1, t1, -ICACHE_LINESIZE +4: + CACHE((C_IINV|CACH_PI), (t0)) + .set noreorder + bltu t0, t1, 4b + addiu t0, t0, ICACHE_LINESIZE + .set reorder + + jr ra + #nop +END(osInvalICache) diff --git a/lib/ultralib/src/os/jammesg.c b/lib/ultralib/src/os/jammesg.c new file mode 100644 index 0000000..289d850 --- /dev/null +++ b/lib/ultralib/src/os/jammesg.c @@ -0,0 +1,27 @@ +#include "PR/os_internal.h" +#include "osint.h" + +s32 osJamMesg(OSMesgQueue *mq, OSMesg msg, s32 flag) { + register u32 saveMask = __osDisableInt(); + + while (mq->validCount >= mq->msgCount) { + if (flag == OS_MESG_BLOCK) { + __osRunningThread->state = OS_STATE_WAITING; + __osEnqueueAndYield(&mq->fullqueue); + } else { + __osRestoreInt(saveMask); + return -1; + } + } + + mq->first = (mq->first + mq->msgCount - 1) % mq->msgCount; + mq->msg[mq->first] = msg; + mq->validCount++; + + if (mq->mtqueue->next != NULL) { + osStartThread(__osPopThread(&mq->mtqueue)); + } + + __osRestoreInt(saveMask); + return 0; +} diff --git a/lib/ultralib/src/os/kdebugserver.c b/lib/ultralib/src/os/kdebugserver.c new file mode 100644 index 0000000..85dc172 --- /dev/null +++ b/lib/ultralib/src/os/kdebugserver.c @@ -0,0 +1,96 @@ +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "PR/rdb.h" +#include "osint.h" + +extern u32 __osRdb_IP6_Empty; + +// not included in final rom, but __osThreadSave is here for some reason +OSThread __osThreadSave; + +#ifndef _FINALROM + +static u8 buffer[12]; +static u32 numChars = 0; + +static u32 string_to_u32(u8* s) { + u32 k; + + k = ((s[0] & 0xFF) << 0x18); + k |= ((s[1] & 0xFF) << 0x10); + k |= ((s[2] & 0xFF) << 0x8); + k |= (s[3] & 0xFF); + + return k; +} + +static void send_packet(u8* s, u32 n) { + rdbPacket packet; + u32 i; + + packet.type = 0xC; + packet.length = n; + + for (i = 0; i < n; i++) { + packet.buf[i] = s[i]; + } + *(rdbPacket*)RDB_BASE_REG = packet; +} + +static void clear_IP6(void) { + while (!(__osGetCause() & CAUSE_IP6)) { + ; + } + *(u32*)RDB_READ_INTR_REG = 0; + + while (__osGetCause() & CAUSE_IP6) { + ; + } +} + +static void send(u8* s, u32 n) { + u32 ct; + u32 i = 0; + u32 getLastIP6; + + if (!__osRdb_IP6_Empty) { + clear_IP6(); + getLastIP6 = FALSE; + } else { + getLastIP6 = TRUE; + } + while (n != 0) { + ct = (n < 3) ? n : 3; + send_packet(s + i, ct); + n -= ct; + i += ct; + if (n != 0) { + clear_IP6(); + } + } + if (getLastIP6) { + clear_IP6(); + } +} + +void kdebugserver(rdbPacket packet) { + u32 i; + u32 length; + u8* addr; + + for (i = 0; i < 3; i++) { + buffer[numChars++] = packet.buf[i]; + } + + if (buffer[0] == 2) { + send((char*)&__osRunningThread->context, sizeof(__OSThreadContext)); + numChars = 0; + } else if (numChars >= 9 && buffer[0] == 1) { + addr = string_to_u32(&buffer[1]); + length = string_to_u32(&buffer[5]); + send(addr, length); + numChars = 0; + } +} + +#endif diff --git a/lib/ultralib/src/os/maptlb.s b/lib/ultralib/src/os/maptlb.s new file mode 100644 index 0000000..d02e3fd --- /dev/null +++ b/lib/ultralib/src/os/maptlb.s @@ -0,0 +1,64 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +#define index a0 +#define pm a1 +#define vaddr a2 +#define evenpaddr a3 +#define oddpaddr 16(sp) +#define asid 20(sp) +.text +LEAF(osMapTLB) + STAY2(mfc0 t0, C0_ENTRYHI) + STAY2(mtc0 index, C0_INX) + STAY2(mtc0 pm, C0_PAGEMASK) +.set noreorder + lw t1, asid + beq t1, -1, 7f + li ta0, TLBLO_G +.set reorder + li t2, TLBLO_NONCOHRNT | TLBLO_D | TLBLO_V + or vaddr, vaddr, t1 + b 8f + +7: + li t2, TLBLO_NONCOHRNT | TLBLO_D | TLBLO_V | TLBLO_G +8: + STAY2(mtc0 vaddr, C0_ENTRYHI) + beq evenpaddr, -1, 9f + #nop + srl t3, evenpaddr, TLBLO_PFNSHIFT + or t3, t3, t2 + STAY2(mtc0 t3, C0_ENTRYLO0) + b 10f + #nop +9: + STAY2(mtc0 ta0, C0_ENTRYLO0) +10: + lw t3, oddpaddr + beq t3, -1, 11f + #nop + srl t3, t3, TLBLO_PFNSHIFT + or t3, t3, t2 + STAY2(mtc0 t3, C0_ENTRYLO1) + b 12f + #nop +11: + STAY2(mtc0 ta0, C0_ENTRYLO1) + bne evenpaddr, -1, 12f + #nop + li t3, K0BASE + STAY2(mtc0 t3, C0_ENTRYHI) +12: + .set noreorder + nop + tlbwi + nop + nop + nop + nop + STAY2(mtc0 t0, C0_ENTRYHI) + jr ra + #nop +END(osMapTLB) diff --git a/lib/ultralib/src/os/maptlbrdb.s b/lib/ultralib/src/os/maptlbrdb.s new file mode 100644 index 0000000..c004362 --- /dev/null +++ b/lib/ultralib/src/os/maptlbrdb.s @@ -0,0 +1,30 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osMapTLBRdb) + mfc0 t0, C0_ENTRYHI + li t1, 31 + mtc0 t1, C0_INX + mtc0 zero, C0_PAGEMASK /*4k*/ + li t2, TLBLO_UNCACHED | TLBLO_D | TLBLO_V | TLBLO_G + li t1, K2BASE + mtc0 t1, C0_ENTRYHI + li t1, KUSIZE + srl t3, t1,TLBLO_PFNSHIFT + or t3, t3,t2 + mtc0 t3, C0_ENTRYLO0 + li t1, TLBLO_G + mtc0 t1, C0_ENTRYLO1 + nop + tlbwi + nop + nop + nop + nop + mtc0 t0, C0_ENTRYHI + jr ra + nop +END(osMapTLBRdb) diff --git a/lib/ultralib/src/os/osint.h b/lib/ultralib/src/os/osint.h new file mode 100644 index 0000000..7a4c0cd --- /dev/null +++ b/lib/ultralib/src/os/osint.h @@ -0,0 +1,55 @@ +#ifndef _OSINT_H +#define _OSINT_H +#include "PR/os_internal.h" +typedef struct __OSEventState +{ + OSMesgQueue *messageQueue; + OSMesg message; +} __OSEventState; +extern struct __osThreadTail +{ + OSThread *next; + OSPri priority; +} __osThreadTail; + +//maybe should be in exceptasm.h? +extern void __osEnqueueAndYield(OSThread **); +extern void __osDequeueThread(OSThread **, OSThread *); +extern void __osEnqueueThread(OSThread **, OSThread *); +extern OSThread *__osPopThread(OSThread **); +extern void __osDispatchThread(void); +extern void __osCleanupThread(void); + +extern void __osSetTimerIntr(OSTime); +extern OSTime __osInsertTimer(OSTimer *); +extern void __osTimerInterrupt(void); +extern u32 __osProbeTLB(void *); +extern int __osSpDeviceBusy(void); + +extern OSThread *__osRunningThread; +extern OSThread *__osActiveQueue; +extern OSThread *__osFaultedThread; +extern OSThread *__osRunQueue; + +extern OSTimer *__osTimerList; +extern OSTimer __osBaseTimer; +extern OSTime __osCurrentTime; +extern u32 __osBaseCounter; +extern u32 __osViIntrCount; +extern u32 __osTimerCounter; +extern u32 __osShutdown; + +extern __OSEventState __osEventStateTab[OS_NUM_EVENTS]; + + +//not sure if this should be here +extern s32 osViClock; +extern void __osTimerServicesInit(void); +extern s32 __osAiDeviceBusy(void); +extern int __osDpDeviceBusy(void); + +#ifndef _FINALROM +extern void* __printfunc; +#endif + +#endif diff --git a/lib/ultralib/src/os/parameters.s b/lib/ultralib/src/os/parameters.s new file mode 100644 index 0000000..ce6ebb5 --- /dev/null +++ b/lib/ultralib/src/os/parameters.s @@ -0,0 +1,16 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +ABS(leoBootID, 0x800001a0) +ABS(osTvType, 0x80000300) +ABS(osRomType, 0x80000304) +ABS(osRomBase, 0x80000308) +ABS(osResetType, 0x8000030c) +ABS(osCicId, 0x80000310) +ABS(osVersion, 0x80000314) +ABS(osMemSize, 0x80000318) +ABS(osAppNMIBuffer, 0x8000031c) +.fill 0x60 +/* padded to 0x60 in the object file */ diff --git a/lib/ultralib/src/os/physicaltovirtual.c b/lib/ultralib/src/os/physicaltovirtual.c new file mode 100644 index 0000000..a0c1bae --- /dev/null +++ b/lib/ultralib/src/os/physicaltovirtual.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" + +void *osPhysicalToVirtual(u32 addr) { + return (void *)PHYS_TO_K0(addr); +} diff --git a/lib/ultralib/src/os/probetlb.s b/lib/ultralib/src/os/probetlb.s new file mode 100644 index 0000000..237db23 --- /dev/null +++ b/lib/ultralib/src/os/probetlb.s @@ -0,0 +1,54 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(__osProbeTLB) + mfc0 t0, C0_ENTRYHI + andi t1, t0, TLBHI_PIDMASK + and t2, a0, -8192 # This also works: (TLBHI_VPN2MASK << 32) >> 32 + or t1, t1, t2 + mtc0 t1, C0_ENTRYHI + nop + nop + nop + tlbp + nop + nop + mfc0 t3, C0_INX + and t3, t3, TLBINX_PROBE + bnez t3, 3f + nop + tlbr + nop + nop + nop + mfc0 t3, C0_PAGEMASK + addi t3, t3, DCACHE_SIZE + srl t3, t3, 0x1 + and ta0, t3, a0 + bnez ta0, 1f + addi t3, t3,-1 + mfc0 v0, C0_ENTRYLO0 + b 2f + nop +1: + mfc0 v0, C0_ENTRYLO1 +2: + andi ta1, v0,TLBLO_V + beqz ta1, 3f + nop + and v0, v0, TLBLO_PFNMASK + sll v0, v0, TLBLO_PFNSHIFT + and ta1, a0, t3 + add v0, v0, ta1 + b 4f + nop +3: + li v0, -1 +4: + mtc0 t0, C0_ENTRYHI + jr ra + nop +END(__osProbeTLB) diff --git a/lib/ultralib/src/os/rdbsend.c b/lib/ultralib/src/os/rdbsend.c new file mode 100644 index 0000000..b561d99 --- /dev/null +++ b/lib/ultralib/src/os/rdbsend.c @@ -0,0 +1 @@ +/* this file is completely empty in the rom release */ diff --git a/lib/ultralib/src/os/recvmesg.c b/lib/ultralib/src/os/recvmesg.c new file mode 100644 index 0000000..f7f0e63 --- /dev/null +++ b/lib/ultralib/src/os/recvmesg.c @@ -0,0 +1,31 @@ +#include "PR/os_internal.h" +#include "osint.h" + +s32 osRecvMesg(OSMesgQueue *mq, OSMesg *msg, s32 flags) { + register u32 saveMask; + saveMask = __osDisableInt(); + + while (MQ_IS_EMPTY(mq)) { + if (flags == OS_MESG_NOBLOCK) { + __osRestoreInt(saveMask); + return -1; + } + + __osRunningThread->state = OS_STATE_WAITING; + __osEnqueueAndYield(&mq->mtqueue); + } + + if (msg != NULL) { + *msg = mq->msg[mq->first]; + } + + mq->first = (mq->first + 1) % mq->msgCount; + mq->validCount--; + + if (mq->fullqueue->next != NULL) { + osStartThread(__osPopThread(&mq->fullqueue)); + } + + __osRestoreInt(saveMask); + return 0; +} diff --git a/lib/ultralib/src/os/resetglobalintmask.c b/lib/ultralib/src/os/resetglobalintmask.c new file mode 100644 index 0000000..780da7c --- /dev/null +++ b/lib/ultralib/src/os/resetglobalintmask.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" + +void __osResetGlobalIntMask(OSHWIntr mask) { + register u32 saveMask = __osDisableInt(); + + __OSGlobalIntMask &= ~(mask & ~OS_IM_RCP); + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/sendmesg.c b/lib/ultralib/src/os/sendmesg.c new file mode 100644 index 0000000..4d48d08 --- /dev/null +++ b/lib/ultralib/src/os/sendmesg.c @@ -0,0 +1,28 @@ +#include "PR/os_internal.h" +#include "osint.h" + +s32 osSendMesg(OSMesgQueue *mq, OSMesg msg, s32 flags) { + register u32 saveMask; + register s32 last; + saveMask = __osDisableInt(); + while (MQ_IS_FULL(mq)) { + if (flags == OS_MESG_BLOCK) { + __osRunningThread->state = OS_STATE_WAITING; + __osEnqueueAndYield(&mq->fullqueue); + } else { + __osRestoreInt(saveMask); + return -1; + } + } + + last = (mq->first + mq->validCount) % mq->msgCount; + mq->msg[last] = msg; + mq->validCount++; + + if (mq->mtqueue->next != NULL) { + osStartThread(__osPopThread(&mq->mtqueue)); + } + + __osRestoreInt(saveMask); + return 0; +} diff --git a/lib/ultralib/src/os/setcause.s b/lib/ultralib/src/os/setcause.s new file mode 100644 index 0000000..52e4950 --- /dev/null +++ b/lib/ultralib/src/os/setcause.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetCause) + STAY2(mtc0 a0, C0_CAUSE) + jr ra +END(__osSetCause) diff --git a/lib/ultralib/src/os/setcompare.s b/lib/ultralib/src/os/setcompare.s new file mode 100644 index 0000000..dec29a2 --- /dev/null +++ b/lib/ultralib/src/os/setcompare.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetCompare) + STAY2(mtc0 a0, C0_COMPARE) + jr ra +END(__osSetCompare) diff --git a/lib/ultralib/src/os/setconfig.s b/lib/ultralib/src/os/setconfig.s new file mode 100644 index 0000000..4f062bd --- /dev/null +++ b/lib/ultralib/src/os/setconfig.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetConfig) + STAY2(mtc0 a0, C0_CONFIG) + jr ra +END(__osSetConfig) diff --git a/lib/ultralib/src/os/setcount.s b/lib/ultralib/src/os/setcount.s new file mode 100644 index 0000000..f94f1d2 --- /dev/null +++ b/lib/ultralib/src/os/setcount.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetCount) + STAY2(mtc0 a0, C0_COUNT) + jr ra +END(__osSetCount) diff --git a/lib/ultralib/src/os/seterrorhandler.c b/lib/ultralib/src/os/seterrorhandler.c new file mode 100644 index 0000000..4e839e8 --- /dev/null +++ b/lib/ultralib/src/os/seterrorhandler.c @@ -0,0 +1,10 @@ +#include "PR/ultraerror.h" + +extern OSErrorHandler __osErrorHandler; + +OSErrorHandler osSetErrorHandler(OSErrorHandler handler) { + OSErrorHandler oldHandler = __osErrorHandler; + + __osErrorHandler = handler; + return oldHandler; +} diff --git a/lib/ultralib/src/os/seteventmesg.c b/lib/ultralib/src/os/seteventmesg.c new file mode 100644 index 0000000..dd2ad99 --- /dev/null +++ b/lib/ultralib/src/os/seteventmesg.c @@ -0,0 +1,23 @@ +#include "macros.h" +#include "PR/os_internal.h" +#include "osint.h" + +__OSEventState __osEventStateTab[OS_NUM_EVENTS] ALIGNED(8); +u32 __osPreNMI = FALSE; + +void osSetEventMesg(OSEvent event, OSMesgQueue *mq, OSMesg msg) { + register u32 saveMask = __osDisableInt(); + __OSEventState *es = &__osEventStateTab[event]; + + es->messageQueue = mq; + es->message = msg; + + if (event == OS_EVENT_PRENMI) { + if (__osShutdown && !__osPreNMI) { + osSendMesg(mq, msg, OS_MESG_NOBLOCK); + } + __osPreNMI = TRUE; + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/setfpccsr.s b/lib/ultralib/src/os/setfpccsr.s new file mode 100644 index 0000000..f96ab33 --- /dev/null +++ b/lib/ultralib/src/os/setfpccsr.s @@ -0,0 +1,11 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetFpcCsr) + STAY2(cfc1 v0, fcr31) + STAY2(ctc1 a0, fcr31) + jr ra +END(__osSetFpcCsr) +.globl __osSetSR diff --git a/lib/ultralib/src/os/setglobalintmask.c b/lib/ultralib/src/os/setglobalintmask.c new file mode 100644 index 0000000..1d82b6e --- /dev/null +++ b/lib/ultralib/src/os/setglobalintmask.c @@ -0,0 +1,9 @@ +#include "PR/os_internal.h" + +void __osSetGlobalIntMask(OSHWIntr mask) { + register u32 saveMask = __osDisableInt(); + + __OSGlobalIntMask |= mask; + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/sethwinterrupt.c b/lib/ultralib/src/os/sethwinterrupt.c new file mode 100644 index 0000000..0fc9d30 --- /dev/null +++ b/lib/ultralib/src/os/sethwinterrupt.c @@ -0,0 +1,16 @@ +#include "PR/os_internal.h" + +struct __osHwInt { + s32 (*handler)(void); + void *stackEnd; +}; + +extern struct __osHwInt __osHwIntTable[]; + +void __osSetHWIntrRoutine(OSHWIntr interrupt, s32 (*handler)(void), void *stackEnd) { + register u32 saveMask= __osDisableInt(); + + __osHwIntTable[interrupt].handler = handler; + __osHwIntTable[interrupt].stackEnd = stackEnd; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/setintmask.s b/lib/ultralib/src/os/setintmask.s new file mode 100644 index 0000000..f19ed17 --- /dev/null +++ b/lib/ultralib/src/os/setintmask.s @@ -0,0 +1,124 @@ +#include "PR/R4300.h" +#include "PR/rcp.h" +#include "PR/os.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +#define MI_INTR_MASK ((1 << 6) - 1) + +.globl __osRcpImTable + +.text +.set noreorder +LEAF(osSetIntMask) + mfc0 ta0, C0_SR + + andi v0, ta0, OS_IM_CPU + + la t0, __OSGlobalIntMask + lw t3, 0(t0) + + xor t0, t3,-1 + andi t0, t0,(SR_IMASK) + or v0, v0,t0 + + lw t2, PHYS_TO_K1(MI_INTR_MASK_REG) + beqz t2, 1f + srl t1, t3,0x10 + + xor t1, t1,-1 + andi t1, t1, MI_INTR_MASK + or t2, t2,t1 +1: + sll t2, t2,0x10 + or v0, v0,t2 + + and t0, a0, MI_INTR_MASK<<0x10 + and t0, t0,t3 + srl t0, t0,0xf + lhu t2, __osRcpImTable(t0) + sw t2, PHYS_TO_K1(MI_INTR_MASK_REG) + + andi t0, a0, OS_IM_CPU + andi t1, t3, SR_IMASK + and t0, t0,t1 + + and ta0, ta0, ~SR_IMASK + or ta0, ta0,t0 + + mtc0 ta0, C0_SR + nop + nop + jr ra + nop +END(osSetIntMask) + +.rdata +EXPORT(__osRcpImTable) +/* LUT to convert between MI_INTR and MI_INTR_MASK */ +/* MI_INTR is status for each interrupt whereas */ +/* MI_INTR_MASK has seperate bits for set/clr */ +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP +.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP diff --git a/lib/ultralib/src/os/setpiinterrupt.c b/lib/ultralib/src/os/setpiinterrupt.c new file mode 100644 index 0000000..ddc3f2f --- /dev/null +++ b/lib/ultralib/src/os/setpiinterrupt.c @@ -0,0 +1,16 @@ +#include "PR/os_internal.h" + +struct __osHwInt { + s32 (*handler)(void); + void *stackEnd; +}; + +extern struct __osHwInt __osPiIntTable; + +void __osSetPIIntrRoutine(struct __osHwInt *ir) { + register u32 saveMask= __osDisableInt(); + + __osPiIntTable.handler = ir->handler; + __osPiIntTable.stackEnd = ir->stackEnd; + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/setsr.s b/lib/ultralib/src/os/setsr.s new file mode 100644 index 0000000..c2eb1d7 --- /dev/null +++ b/lib/ultralib/src/os/setsr.s @@ -0,0 +1,10 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetSR) + STAY2(mtc0 a0, C0_SR) + nop + jr ra +END(__osSetSR) diff --git a/lib/ultralib/src/os/setthreadpri.c b/lib/ultralib/src/os/setthreadpri.c new file mode 100644 index 0000000..ab6b23e --- /dev/null +++ b/lib/ultralib/src/os/setthreadpri.c @@ -0,0 +1,26 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osSetThreadPri(OSThread *t, OSPri pri) { + register u32 saveMask = __osDisableInt(); + + if (t == NULL) { + t = __osRunningThread; + } + + if (t->priority != pri) { + t->priority = pri; + + if (t != __osRunningThread && t->state != OS_STATE_STOPPED) { + __osDequeueThread(t->queue, t); + __osEnqueueThread(t->queue, t); + } + + if (__osRunningThread->priority < __osRunQueue->priority) { + __osRunningThread->state = OS_STATE_RUNNABLE; + __osEnqueueAndYield(&__osRunQueue); + } + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/settime.c b/lib/ultralib/src/os/settime.c new file mode 100644 index 0000000..5bae2a2 --- /dev/null +++ b/lib/ultralib/src/os/settime.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osSetTime(OSTime time) { + __osCurrentTime = time; +} diff --git a/lib/ultralib/src/os/settimer.c b/lib/ultralib/src/os/settimer.c new file mode 100644 index 0000000..0b78f27 --- /dev/null +++ b/lib/ultralib/src/os/settimer.c @@ -0,0 +1,41 @@ +#include "PR/os_internal.h" +#include "osint.h" + +int osSetTimer(OSTimer *t, OSTime countdown, OSTime interval, OSMesgQueue *mq, OSMesg msg) { + register u32 saveMask; + OSTime time; + OSTimer* next; + u32 count; + u32 value; + + t->next = NULL; + t->prev = NULL; + t->value = countdown; + t->interval = interval; + + if (countdown == 0) { + t->value = interval; + } + + t->mq = mq; + t->msg = msg; + + saveMask = __osDisableInt(); + if (__osTimerList->next != __osTimerList) { + next = __osTimerList->next; + count = osGetCount(); + value = count - __osTimerCounter; + + if (value < next->value) { + next->value -= value; + } else { + next->value = 1; + } + } + + time = __osInsertTimer(t); + __osSetTimerIntr(__osTimerList->next->value); + __osRestoreInt(saveMask); + + return 0; +} diff --git a/lib/ultralib/src/os/settlbasid.s b/lib/ultralib/src/os/settlbasid.s new file mode 100644 index 0000000..efaed5e --- /dev/null +++ b/lib/ultralib/src/os/settlbasid.s @@ -0,0 +1,9 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(osSetTLBASID) + STAY2(mtc0 a0, C0_ENTRYHI) + jr ra +END(osSetTLBASID) diff --git a/lib/ultralib/src/os/setwatchlo.s b/lib/ultralib/src/os/setwatchlo.s new file mode 100644 index 0000000..2f645a7 --- /dev/null +++ b/lib/ultralib/src/os/setwatchlo.s @@ -0,0 +1,10 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(__osSetWatchLo) + STAY2(mtc0 a0, C0_WATCHLO) + nop + jr ra +END(__osSetWatchLo) diff --git a/lib/ultralib/src/os/startthread.c b/lib/ultralib/src/os/startthread.c new file mode 100644 index 0000000..dfd7f1c --- /dev/null +++ b/lib/ultralib/src/os/startthread.c @@ -0,0 +1,35 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osStartThread(OSThread *t) { + register u32 saveMask = __osDisableInt(); + + switch (t->state) { + case OS_STATE_WAITING: + t->state = OS_STATE_RUNNABLE; + __osEnqueueThread(&__osRunQueue, t); + break; + case OS_STATE_STOPPED: + if (t->queue == NULL || t->queue == &__osRunQueue) + { + t->state = OS_STATE_RUNNABLE; + __osEnqueueThread(&__osRunQueue, t); + } + else + { + t->state = OS_STATE_WAITING; + __osEnqueueThread(t->queue, t); + __osEnqueueThread(&__osRunQueue, __osPopThread(t->queue)); + } + break; + } + + if (__osRunningThread == NULL) { + __osDispatchThread(); + } else if (__osRunningThread->priority < __osRunQueue->priority) { + __osRunningThread->state = OS_STATE_RUNNABLE; + __osEnqueueAndYield(&__osRunQueue); + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/stopthread.c b/lib/ultralib/src/os/stopthread.c new file mode 100644 index 0000000..d276b3b --- /dev/null +++ b/lib/ultralib/src/os/stopthread.c @@ -0,0 +1,25 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osStopThread(OSThread *t) { + register u32 saveMask = __osDisableInt(); + register u16 state = OS_STATE_RUNNING; + + if (t != NULL) { + state = t->state; + } + + switch (state) { + case OS_STATE_RUNNING: + __osRunningThread->state = OS_STATE_STOPPED; + __osEnqueueAndYield(NULL); + break; + case OS_STATE_RUNNABLE: + case OS_STATE_WAITING: + t->state = OS_STATE_STOPPED; + __osDequeueThread(t->queue, t); + break; + } + + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/os/stoptimer.c b/lib/ultralib/src/os/stoptimer.c new file mode 100644 index 0000000..e9e07af --- /dev/null +++ b/lib/ultralib/src/os/stoptimer.c @@ -0,0 +1,30 @@ +#include "PR/os_internal.h" +#include "osint.h" + +int osStopTimer(OSTimer *t) { + register u32 savedMask; + OSTimer *timep; + + if (t->next == NULL) { + return -1; + } + + savedMask = __osDisableInt(); + timep = t->next; + + if (timep != __osTimerList) { + timep->value += t->value; + } + + t->prev->next = t->next; + t->next->prev = t->prev; + t->next = NULL; + t->prev = NULL; + + if (__osTimerList->next == __osTimerList) { + __osSetCompare(0); + } + + __osRestoreInt(savedMask); + return 0; +} diff --git a/lib/ultralib/src/os/syncputchars.c b/lib/ultralib/src/os/syncputchars.c new file mode 100644 index 0000000..9095a04 --- /dev/null +++ b/lib/ultralib/src/os/syncputchars.c @@ -0,0 +1,32 @@ +#include "PR/os_internal.h" +#include "PR/rdb.h" +#include "PR/rcp.h" +#include "PR/R4300.h" + +unsigned int __osRdbSendMessage = 0; +unsigned int __osRdbWriteOK = 1; + +void __osSyncPutChars(int type, int length, const char *buf) { + rdbPacket packet; + int i; + u32 mask; + packet.type = type; + packet.length = length; + + for (i = 0; i < length; i++) { + packet.buf[i] = buf[i]; + } + + while (!__osAtomicDec(&__osRdbWriteOK)) { + } + + mask = __osDisableInt(); + *(vu32 *)RDB_BASE_REG = *(vu32 *)&packet; + + while (!(__osGetCause() & CAUSE_IP6)) { + } + + *(vu32 *)RDB_READ_INTR_REG = 0; + __osRdbWriteOK++; + __osRestoreInt(mask); +} diff --git a/lib/ultralib/src/os/testhost.c b/lib/ultralib/src/os/testhost.c new file mode 100644 index 0000000..70514eb --- /dev/null +++ b/lib/ultralib/src/os/testhost.c @@ -0,0 +1,4 @@ +#include "PR/os_internal.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" diff --git a/lib/ultralib/src/os/thread.c b/lib/ultralib/src/os/thread.c new file mode 100644 index 0000000..767c4cf --- /dev/null +++ b/lib/ultralib/src/os/thread.c @@ -0,0 +1,25 @@ +#include "PR/os_internal.h" +#include "osint.h" + +struct __osThreadTail __osThreadTail = {NULL, -1}; +OSThread *__osRunQueue = (OSThread *)&__osThreadTail; +OSThread *__osActiveQueue = (OSThread *)&__osThreadTail; +OSThread *__osRunningThread = {0}; +OSThread *__osFaultedThread = {0}; + +void __osDequeueThread(OSThread **queue, OSThread *t) { + register OSThread **pred; + register OSThread *succ; + + pred = queue; + succ = *pred; + + while (succ != NULL) { + if (succ == t) { + *pred = t->next; + return; + } + pred = succ; + succ = *pred; + } +} diff --git a/lib/ultralib/src/os/threadasm.h b/lib/ultralib/src/os/threadasm.h new file mode 100644 index 0000000..c5a73da --- /dev/null +++ b/lib/ultralib/src/os/threadasm.h @@ -0,0 +1,68 @@ +#ifndef _THREADASM_H_ +#define _THREADASM_H_ + +// Offsets of members in the OSThread struct +#define THREAD_NEXT 0 +#define THREAD_PRI 4 +#define THREAD_QUEUE 8 +#define THREAD_TLNEXT 12 +#define THREAD_STATE 16 +#define THREAD_FLAGS 18 +#define THREAD_ID 20 +#define THREAD_FP 24 +#define THREAD_GP1 32 +#define THREAD_GP2 40 +#define THREAD_GP3 48 +#define THREAD_GP4 56 +#define THREAD_GP5 64 +#define THREAD_GP6 72 +#define THREAD_GP7 80 +#define THREAD_GP8 88 +#define THREAD_GP9 96 +#define THREAD_GP10 104 +#define THREAD_GP11 112 +#define THREAD_GP12 120 +#define THREAD_GP13 128 +#define THREAD_GP14 136 +#define THREAD_GP15 144 +#define THREAD_GP16 152 +#define THREAD_GP17 160 +#define THREAD_GP18 168 +#define THREAD_GP19 176 +#define THREAD_GP20 184 +#define THREAD_GP21 192 +#define THREAD_GP22 200 +#define THREAD_GP23 208 +#define THREAD_GP24 216 +#define THREAD_GP25 224 +// k0 and k1 are reserved for the kernel +#define THREAD_GP28 232 +#define THREAD_GP29 240 +#define THREAD_GP30 248 +#define THREAD_GP31 256 +#define THREAD_LO 264 +#define THREAD_HI 272 +#define THREAD_SR 280 +#define THREAD_PC 284 +#define THREAD_CAUSE 288 +#define THREAD_BADVADDR 292 +#define THREAD_RCP 296 +#define THREAD_FPCSR 300 +#define THREAD_FP0 304 +#define THREAD_FP2 312 +#define THREAD_FP4 320 +#define THREAD_FP6 328 +#define THREAD_FP8 336 +#define THREAD_FP10 344 +#define THREAD_FP12 352 +#define THREAD_FP14 360 +#define THREAD_FP16 368 +#define THREAD_FP18 376 +#define THREAD_FP20 384 +#define THREAD_FP22 392 +#define THREAD_FP24 400 +#define THREAD_FP26 408 +#define THREAD_FP28 416 +#define THREAD_FP30 424 + +#endif diff --git a/lib/ultralib/src/os/timerintr.c b/lib/ultralib/src/os/timerintr.c new file mode 100644 index 0000000..0f09d1f --- /dev/null +++ b/lib/ultralib/src/os/timerintr.c @@ -0,0 +1,106 @@ +#include "PR/os_internal.h" +#include "osint.h" + +OSTimer *__osTimerList = &__osBaseTimer; +OSTimer __osBaseTimer; +OSTime __osCurrentTime; +u32 __osBaseCounter; +u32 __osViIntrCount; +u32 __osTimerCounter; + +void __osTimerServicesInit(void) { + __osCurrentTime = 0; + __osBaseCounter = 0; + __osViIntrCount = 0; + __osTimerList->prev = __osTimerList; + __osTimerList->next = __osTimerList->prev; + __osTimerList->value = 0; + __osTimerList->interval = __osTimerList->value; + __osTimerList->mq = NULL; + __osTimerList->msg = 0; +} + +void __osTimerInterrupt(void) { + OSTimer *t; + u32 count; + u32 elapsed_cycles; + + if (__osTimerList->next != __osTimerList) { + while (TRUE) { + t = __osTimerList->next; + if (t == __osTimerList) { + __osSetCompare(0); + __osTimerCounter = 0; + break; + } + + count = osGetCount(); + elapsed_cycles = count - __osTimerCounter; + __osTimerCounter = count; + + if (elapsed_cycles < t->value) + { + t->value -= elapsed_cycles; + __osSetTimerIntr(t->value); + break; + } else { + t->prev->next = t->next; + t->next->prev = t->prev; + t->next = NULL; + t->prev = NULL; + + if (t->mq != NULL) { + osSendMesg(t->mq, t->msg, OS_MESG_NOBLOCK); + } + + if (t->interval != 0) { + t->value = t->interval; + __osInsertTimer(t); + } + } + } + } +} + +void __osSetTimerIntr(OSTime tim) { + OSTime NewTime; + u32 savedMask; + + if (tim < 468) { + tim = 468; + } + + savedMask = __osDisableInt(); + __osTimerCounter = osGetCount(); + NewTime = __osTimerCounter + tim; + __osSetCompare(NewTime); + __osRestoreInt(savedMask); +} + +OSTime __osInsertTimer(OSTimer *t) { + OSTimer *timep; + OSTime tim; + u32 savedMask; + savedMask = __osDisableInt(); + + timep = __osTimerList->next; + tim = t->value; + + while (timep != __osTimerList && tim > timep->value) { + tim -= timep->value; + timep = timep->next; + } + + t->value = tim; + + if (timep != __osTimerList) { + timep->value -= tim; + } + + t->next = timep; + t->prev = timep->prev; + timep->prev->next = t; + timep->prev = t; + __osRestoreInt(savedMask); + return tim; +} diff --git a/lib/ultralib/src/os/unmaptlb.s b/lib/ultralib/src/os/unmaptlb.s new file mode 100644 index 0000000..280a42e --- /dev/null +++ b/lib/ultralib/src/os/unmaptlb.s @@ -0,0 +1,24 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osUnmapTLB) + mfc0 t0, C0_ENTRYHI + mtc0 a0, C0_INX + li t1, K0BASE + mtc0 t1, C0_ENTRYHI + mtc0 zero, C0_ENTRYLO0 + mtc0 zero, C0_ENTRYLO1 + nop + tlbwi + nop + nop + nop + nop + mtc0 t0, C0_ENTRYHI + jr ra + nop +END(osUnmapTLB) + diff --git a/lib/ultralib/src/os/unmaptlball.s b/lib/ultralib/src/os/unmaptlball.s new file mode 100644 index 0000000..6d4b264 --- /dev/null +++ b/lib/ultralib/src/os/unmaptlball.s @@ -0,0 +1,26 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +.set noreorder +LEAF(osUnmapTLBAll) + mfc0 t0, C0_ENTRYHI + li t1, NTLBENTRIES-1 /* last reserved for rdb */ + li t2, KUSIZE + mtc0 t2, C0_ENTRYHI + mtc0 zero, C0_ENTRYLO0 + mtc0 zero, C0_ENTRYLO1 +1: + mtc0 t1, C0_INX + nop + tlbwi + nop + nop + addi t1, t1,-1 + bgez t1, 1b + nop + mtc0 t0, C0_ENTRYHI + jr ra + nop +END(osUnmapTLBAll) diff --git a/lib/ultralib/src/os/virtualtophysical.c b/lib/ultralib/src/os/virtualtophysical.c new file mode 100644 index 0000000..5cf9e86 --- /dev/null +++ b/lib/ultralib/src/os/virtualtophysical.c @@ -0,0 +1,13 @@ +#include "PR/os_internal.h" +#include "PR/R4300.h" +#include "osint.h" + +u32 osVirtualToPhysical(void *addr) { + if (IS_KSEG0(addr)) { + return K0_TO_PHYS(addr); + } else if (IS_KSEG1(addr)) { + return K1_TO_PHYS(addr); + } else { + return __osProbeTLB(addr); + } +} diff --git a/lib/ultralib/src/os/writebackdcache.s b/lib/ultralib/src/os/writebackdcache.s new file mode 100644 index 0000000..5f5b485 --- /dev/null +++ b/lib/ultralib/src/os/writebackdcache.s @@ -0,0 +1,35 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(osWritebackDCache) + blez a1, 2f + li t3, DCACHE_SIZE + bgeu a1,t3, 3f + move t0, a0 + addu t1, a0,a1 + bgeu t0, t1, 2f + addiu t1, t1, -DCACHE_LINESIZE + andi t2, t0, DCACHE_LINEMASK + subu t0, t0,t2 +1: + .set noreorder + cache (C_HWB|CACH_PD), (t0) + bltu t0, t1, 1b + addiu t0, t0, DCACHE_LINESIZE + .set reorder +2: + jr ra +3: + li t0, KUSIZE + addu t1, t0,t3 + addiu t1, t1, -DCACHE_LINESIZE +4: + .set noreorder + cache (C_IWBINV|CACH_PD), (t0) + bltu t0, t1, 4b + addiu t0, t0, DCACHE_LINESIZE + .set reorder + jr ra +END(osWritebackDCache) diff --git a/lib/ultralib/src/os/writebackdcacheall.s b/lib/ultralib/src/os/writebackdcacheall.s new file mode 100644 index 0000000..ee8df88 --- /dev/null +++ b/lib/ultralib/src/os/writebackdcacheall.s @@ -0,0 +1,18 @@ +#include "PR/R4300.h" +#include "sys/asm.h" +#include "sys/regdef.h" + +.text +LEAF(osWritebackDCacheAll) + li t0, KUSIZE + li t2, DCACHE_SIZE + addu t1, t0,t2 + addiu t1, t1, -DCACHE_LINESIZE +1: + .set noreorder + cache (C_IWBINV | CACH_PD), (t0) + bltu t0, t1, 1b + addiu t0, t0, DCACHE_LINESIZE + .set reorder + jr ra +END(osWritebackDCacheAll) diff --git a/lib/ultralib/src/os/yieldthread.c b/lib/ultralib/src/os/yieldthread.c new file mode 100644 index 0000000..f4ed7c5 --- /dev/null +++ b/lib/ultralib/src/os/yieldthread.c @@ -0,0 +1,10 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osYieldThread(void) { + register u32 saveMask = __osDisableInt(); + + __osRunningThread->state = OS_STATE_RUNNABLE; + __osEnqueueAndYield(&__osRunQueue); + __osRestoreInt(saveMask); +} diff --git a/lib/ultralib/src/rg/free.c b/lib/ultralib/src/rg/free.c new file mode 100755 index 0000000..0229b2c --- /dev/null +++ b/lib/ultralib/src/rg/free.c @@ -0,0 +1,15 @@ +#include "PR/region.h" +#include "PR/R4300.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void osFree(void *region, void *addr) { + register OSRegion *rp = region; + int i; + + rp = region; + i = ((u8 *)addr - rp->r_startBufferAddress) / rp->r_bufferSize; + *(u16 *)(&rp->r_startBufferAddress[i * rp->r_bufferSize]) = rp->r_freeList; + rp->r_freeList = i; +} diff --git a/lib/ultralib/src/rg/getbufcount.c b/lib/ultralib/src/rg/getbufcount.c new file mode 100755 index 0000000..4f61521 --- /dev/null +++ b/lib/ultralib/src/rg/getbufcount.c @@ -0,0 +1,10 @@ +#include "PR/region.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osGetRegionBufCount(void *region) { + register OSRegion *rp = region; + return rp->r_bufferCount; +} + diff --git a/lib/ultralib/src/rg/getsize.c b/lib/ultralib/src/rg/getsize.c new file mode 100755 index 0000000..6bd4b2a --- /dev/null +++ b/lib/ultralib/src/rg/getsize.c @@ -0,0 +1,9 @@ +#include "PR/region.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +s32 osGetRegionBufSize(void *region) { + register OSRegion *rp = region; + return rp->r_bufferSize; +} diff --git a/lib/ultralib/src/rg/malloc.c b/lib/ultralib/src/rg/malloc.c new file mode 100755 index 0000000..4b26431 --- /dev/null +++ b/lib/ultralib/src/rg/malloc.c @@ -0,0 +1,17 @@ +#include "PR/region.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void *osMalloc(void *region) { + register OSRegion *rp = region; + unsigned char *addr; + + if (rp->r_freeList == MAX_BUFCOUNT) { + return NULL; + } + + addr = &rp->r_startBufferAddress[rp->r_freeList * rp->r_bufferSize]; + rp->r_freeList = *(u16 *)addr; + return addr; +} diff --git a/lib/ultralib/src/rg/region.c b/lib/ultralib/src/rg/region.c new file mode 100755 index 0000000..181f52f --- /dev/null +++ b/lib/ultralib/src/rg/region.c @@ -0,0 +1,36 @@ +#include "PR/region.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +void *osCreateRegion(void *startAddress, u32 length, u32 bufferSize, u32 alignSize) { + register OSRegion *rp; + register int i; + register unsigned char *addr; + + if (alignSize == 0) { + alignSize = OS_RG_ALIGN_DEFAULT; + } + + rp = (OSRegion*)ALIGN(startAddress, alignSize); + length = length - ((s32)rp - (s32)startAddress); + rp->r_bufferSize = ALIGN(bufferSize, alignSize); + rp->r_bufferCount = (s32)(length - ALIGN(sizeof(OSRegion), alignSize)) / rp->r_bufferSize; + + if (rp->r_bufferCount > MAX_BUFCOUNT) { + rp->r_bufferCount = MAX_BUFCOUNT; + } + + rp->r_startBufferAddress = (u8*)rp + ALIGN(sizeof(OSRegion), alignSize); + rp->r_endAddress = (u8*)rp + length; + addr = rp->r_startBufferAddress; + + for (i = 0; i < rp->r_bufferCount - 1; i++) { + *((s16 *)(&addr[i * rp->r_bufferSize])) = i + 1; + } + + *((u16 *)(&addr[i * rp->r_bufferSize])) = BUF_FREE_WO_NEXT; + rp->r_alignSize = alignSize; + rp->r_freeList = 0; + return rp; +} diff --git a/lib/ultralib/src/rmon/rmonbrk.c b/lib/ultralib/src/rmon/rmonbrk.c new file mode 100644 index 0000000..ccae395 --- /dev/null +++ b/lib/ultralib/src/rmon/rmonbrk.c @@ -0,0 +1,423 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "dbgproto.h" +#include "PR/rcp.h" +#include "PR/sptask.h" +#include "rmonint.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +static void rmonFindFaultedThreads(void); + +#define TMP_BP 0 +#define NUM_BREAKPOINTS 16 + +typedef struct { + TVushort type; + TVushort response; + TVid threadID; + void* pc; +} TVExceptionReplyMsg; + +typedef struct { + u32* breakAddress; + u32 oldInstruction; +} BREAKINFO; + +/* first breakpoint is reserved for implementing single-stepping */ +static BREAKINFO breakpoints[NUM_BREAKPOINTS] ALIGNED(8); +/* breakpoint for alternate branch target */ +static BREAKINFO altBreak; + +static BREAKINFO RCPbreakpoints[NUM_BREAKPOINTS] ALIGNED(8); + +u8 __rmonRcpAtBreak; + +static void SetTempBreakpoint(u32* addr1, u32* addr2) { + STUBBED_PRINTF(("Set temp BP at %08x", addr1)); + if (addr2 != NULL) { + STUBBED_PRINTF((" and %08x", addr2)); + } + STUBBED_PRINTF(("\n")); + + /* Save the word at the target address to be restored later */ + breakpoints[TMP_BP].oldInstruction = *addr1; + /* Install a break instruction at the target address */ + *addr1 = MIPS_BREAK(16); + osWritebackDCache(addr1, sizeof(*addr1)); + osInvalICache(addr1, sizeof(*addr1)); + breakpoints[TMP_BP].breakAddress = addr1; + + /* Also do so for an alt address if required */ + if (addr2 != NULL) { + altBreak.oldInstruction = *addr2; + *addr2 = MIPS_BREAK(16); + osWritebackDCache(addr2, sizeof(*addr2)); + osInvalICache(addr2, sizeof(*addr2)); + altBreak.breakAddress = addr2; + } +} + +static void ClearTempBreakpoint(void) { + u32 inst; + + if (breakpoints[TMP_BP].breakAddress != NULL) { + inst = *breakpoints[TMP_BP].breakAddress; + + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + STUBBED_PRINTF(("ClearTempBreak @ %08x\n", breakpoints[TMP_BP].breakAddress)); + + /* After confirming that there is a break instruction with code at the target + address, restore the original contents of the word at the target address */ + *breakpoints[TMP_BP].breakAddress = breakpoints[TMP_BP].oldInstruction; + osWritebackDCache(breakpoints[TMP_BP].breakAddress, sizeof(*breakpoints[TMP_BP].breakAddress)); + osInvalICache(breakpoints[TMP_BP].breakAddress, sizeof(*breakpoints[TMP_BP].breakAddress)); + } + breakpoints[TMP_BP].breakAddress = NULL; + } + + /* Same as above for the alt breakpoint */ + if (altBreak.breakAddress != NULL) { + inst = *altBreak.breakAddress; + + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + STUBBED_PRINTF(("ClearTempBreak @ %08x\n", altBreak.breakAddress)); + + *altBreak.breakAddress = altBreak.oldInstruction; + osWritebackDCache(altBreak.breakAddress, sizeof(*altBreak.breakAddress)); + osInvalICache(altBreak.breakAddress, sizeof(*altBreak.breakAddress)); + } + altBreak.breakAddress = NULL; + } +} + +int __rmonSetBreak(KKHeader* req) { + register KKSetBkptRequest* request = (KKSetBkptRequest*)req; + register BREAKINFO* breakBase; + register BREAKINFO* whichBreak; + register BREAKINFO* lastBreak; + KKBkptEvent reply; + + STUBBED_PRINTF(("SetBreak at %08x, method %d\n", request->addr, req->method)); + + /* Select breakpoint list */ + if (req->method == RMON_RSP) { + breakBase = RCPbreakpoints; + whichBreak = &RCPbreakpoints[1]; + lastBreak = &RCPbreakpoints[NUM_BREAKPOINTS]; + } else { + breakBase = breakpoints; + whichBreak = &breakpoints[1]; + lastBreak = &breakpoints[NUM_BREAKPOINTS]; + } + + /* Find breakpoint slot */ + for (; whichBreak < lastBreak; whichBreak++) { + if (whichBreak->breakAddress != NULL) { + if (whichBreak->breakAddress == (u32*)request->addr) { + /* Breakpoint already set here */ + break; + } + continue; + } else { + /* Empty slot */ + break; + } + } + + /* No breakpoints available */ + if (whichBreak == lastBreak) { + return TV_ERROR_NO_MORE_IDS; + } + + /* Set breakpoint if not already set */ + if (whichBreak->breakAddress == NULL) { + if (req->method == RMON_RSP) { + whichBreak->oldInstruction = __rmonReadWordAt((u32*)request->addr); + __rmonWriteWordTo((u32*)request->addr, MIPS_BREAK((whichBreak - breakBase) + NUM_BREAKPOINTS)); + } else { + whichBreak->oldInstruction = *(u32*)request->addr; + *(u32*)request->addr = MIPS_BREAK((whichBreak - breakBase) + NUM_BREAKPOINTS); + osWritebackDCache((void*)request->addr, sizeof(whichBreak->oldInstruction)); + osInvalICache((void*)request->addr, sizeof(whichBreak->oldInstruction)); + } + whichBreak->breakAddress = (u32*)request->addr; + STUBBED_PRINTF(("* (%08x) = %08x (was %08x)\n", whichBreak->breakAddress, *whichBreak->breakAddress, whichBreak->oldInstruction)); + } + + /* Send reply */ + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->object; + reply.bp = whichBreak - breakBase; + reply.instruction = whichBreak->oldInstruction; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonListBreak(KKHeader* request UNUSED) { + STUBBED_PRINTF(("ListBreak\n")); + + return TV_ERROR_ILLEGAL_CALL; +} + +int __rmonClearBreak(KKHeader* req) { + register KKClrBkptRequest* request = (KKClrBkptRequest*)req; + register BREAKINFO* whichBreak; + KKBkptEvent reply; + u32 inst; + + STUBBED_PRINTF(("ClearBreak\n")); + + /* Check valid breakpoint index */ + if (request->bp >= NUM_BREAKPOINTS) { + return TV_ERROR_INVALID_ID; + } + + /* Clear the breakpoint, restore whatever was there before */ + if (req->method == RMON_RSP) { + whichBreak = &RCPbreakpoints[request->bp]; + + if (whichBreak->breakAddress == NULL) { + return TV_ERROR_INVALID_ID; + } + + inst = __rmonReadWordAt(whichBreak->breakAddress); + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + __rmonWriteWordTo(whichBreak->breakAddress, whichBreak->oldInstruction); + } + } else { + whichBreak = &breakpoints[request->bp]; + + if (whichBreak->breakAddress == NULL) { + return TV_ERROR_INVALID_ID; + } + + inst = *whichBreak->breakAddress; + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + *whichBreak->breakAddress = whichBreak->oldInstruction; + osWritebackDCache(whichBreak->breakAddress, sizeof(*whichBreak->breakAddress)); + osInvalICache(whichBreak->breakAddress, sizeof(*whichBreak->breakAddress)); + } + } + whichBreak->breakAddress = NULL; + + /* Send reply */ + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->object; + reply.bp = request->bp; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +u32 __rmonGetBranchTarget(int method, int thread, char* addr) { + int inst; + + if (method == RMON_RSP) { + inst = __rmonReadWordAt((u32*)addr); + } else { + inst = *(u32*)addr; + } + + switch ((inst >> 26) & 0x3F) { + case 0: /* SPECIAL */ + if (((inst >> 5) & 0x7FFF) == 0 && (inst & 0x3F) == 8) { + /* JR */ + return __rmonGetRegisterContents(method, thread, (inst >> 21) & 0x1F); + } + if (((inst >> 16) & 0x1F) == 0 && (inst & 0x7FF) == 9) { + /* JALR */ + return __rmonGetRegisterContents(method, thread, (inst >> 21) & 0x1F); + } + break; + case 1: /* REGIMM */ + switch ((inst >> 16) & 0x1F) { + case 0: /* BLTZ */ + case 1: /* BGEZ */ + case 2: /* BLTZL */ + case 3: /* BGEZL */ + case 16: /* BLTZAL */ + case 17: /* BGEZAL */ + case 18: /* BLTZALL */ + case 19: /* BGEZALL */ + return (u32)addr + ((inst << 0x10) >> 0xE) + 4; + } + break; + case 2: /* J */ + case 3: /* JAL */ + return (((u32)inst << 6) >> 4) + (((s32)((u32)addr + 4) >> 0x1C) << 0x1C); + case 4: /* BEQ */ + case 5: /* BNE */ + case 20: /* BEQL */ + case 21: /* BNEL */ + return (u32)addr + ((inst << 0x10) >> 0xE) + 4; + case 6: /* BLEZ */ + case 7: /* BGTZ */ + case 22: /* BLEZL */ + case 23: /* BGTZL */ + if (((inst >> 16) & 0x1F) == 0) { + return (u32)addr + ((inst << 0x10) >> 0xE) + 4; + } + break; + case 16: /* COP0 */ + case 17: /* COP1 */ + case 18: /* COP2 */ + case 19: /* COP3 */ + if (((inst >> 21) & 0x1F) == 8) { + switch ((inst >> 16) & 0x1F) { + case 0: /* BCzF */ + case 1: /* BCzT */ + case 2: /* BCzFL */ + case 3: /* BCzTL */ + return (u32)addr + ((inst << 0x10) >> 0xE) + 4; + } + } + break; + } + return -1; +} + +static int IsJump(u32 inst) { + switch ((inst >> 26) & 0x3F) { + case 0: /* SPECIAL */ + if (((inst >> 5) & 0x7FFF) == 0 && (inst & 0x3F) == 8) { + /* JR */ + return TRUE; + } + if (((inst >> 16) & 0x1F) == 0 && (inst & 0x7FF) == 9) { + /* JALR */ + return TRUE; + } + break; + case 2: /* J */ + case 3: /* JAL */ + return TRUE; + } + return FALSE; +} + +int __rmonSetSingleStep(int thread, u32* instptr) { + u32 branchTarget = __rmonGetBranchTarget(RMON_CPU, thread, (void*)instptr); + + STUBBED_PRINTF(("SingleStep\n")); + + if ((branchTarget & 3) != 0) { + /* no branch target, set breakpoint at next pc */ + SetTempBreakpoint(instptr + 1, NULL); + } else if ((u32*)branchTarget == instptr) { + /* branch target is this instruction, can't single step here */ + return FALSE; + } else if (IsJump(*instptr) || (u32*)branchTarget == instptr + 2) { + /* unconditional branch, set at branch target */ + SetTempBreakpoint((u32*)branchTarget, NULL); + } else { + /* set two breakpoints for handling conditional branches */ + SetTempBreakpoint((u32*)branchTarget, instptr + 2); + } + return TRUE; +} + +void __rmonGetExceptionStatus(KKStatusEvent* reply) { + reply->status.flags = OS_STATE_STOPPED; + reply->status.why = 2; + reply->status.what = 0; + reply->status.rv = 0; + reply->status.info.major = 2; + reply->status.info.minor = 4; + reply->header.code = KK_CODE_THREAD_STATUS; + reply->header.error = TV_ERROR_NO_ERROR; + reply->header.length = sizeof(*reply); +} + +#define FAULT_BREAKNUM (NUM_BREAKPOINTS - 1) + +static void rmonSendBreakMessage(s32 whichThread, int breakNumber) { + KKStatusEvent reply; + + STUBBED_PRINTF(("Break %d in thread %d\n", breakNumber, whichThread)); + + /* Build thread exception status */ + __rmonGetThreadStatus(RMON_CPU, (whichThread != 0) ? whichThread : RMON_TID_NOTHREAD, &reply); + __rmonGetExceptionStatus(&reply); + + if (breakNumber == FAULT_BREAKNUM) { + /* Hit fault */ + reply.status.info.major = 1; + reply.status.info.minor = 2; + } + if (breakNumber < NUM_BREAKPOINTS) { + breakNumber = 0; + } else { + breakNumber -= NUM_BREAKPOINTS; + } + if (breakNumber != 0) { + /* Break not set by debugger, or set during single-step */ + reply.status.instr = MIPS_BREAK_OPCODE; + } + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_EXCEPTION); +} + +void __rmonHitBreak(void) { + STUBBED_PRINTF(("HitBreak\n")); + + /* Stop all user threads and report faulted threads */ + ClearTempBreakpoint(); + __rmonStopUserThreads(0); + rmonFindFaultedThreads(); +} + +void __rmonHitSpBreak(void) { + KKStatusEvent exceptionReply; + + STUBBED_PRINTF(("Hit SP Break\n")); + + /* Rewind RSP PC by one instruction to return to the location of the break instruction */ + __rmonWriteWordTo((u32*)SP_PC_REG, __rmonReadWordAt((u32*)SP_PC_REG) - 4); + + /* Report RSP break event */ + __rmonGetThreadStatus(RMON_RSP, RMON_TID_RSP, &exceptionReply); + __rmonGetExceptionStatus(&exceptionReply); + __rmonSendReply(&exceptionReply.header, sizeof(exceptionReply), KK_TYPE_EXCEPTION); + __rmonRcpAtBreak = TRUE; +} + +void __rmonHitCpuFault(void) { + STUBBED_PRINTF(("HitCpuFault\n")); + + /* Stop all user threads and report faulted threads */ + __rmonMaskIdleThreadInts(); + __rmonStopUserThreads(0); + rmonFindFaultedThreads(); +} + +static void rmonFindFaultedThreads(void) { + register OSThread* tptr = __osGetActiveQueue(); + + while (tptr->priority != -1) { + if (tptr->priority > OS_PRIORITY_IDLE && tptr->priority <= OS_PRIORITY_APPMAX) { + if (tptr->flags & OS_FLAG_CPU_BREAK) { + int inst = *(u32*)tptr->context.pc; + + STUBBED_PRINTF(("Brk in thread %d @ %08x, inst %08x\r\n", tptr->id, tptr->context.pc, inst)); + + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + rmonSendBreakMessage(tptr->id, inst >> 6); + } else { + rmonSendBreakMessage(tptr->id, 0); + } + } + if (tptr->flags & OS_FLAG_FAULT) { + __rmonSendFault(tptr); + rmonSendBreakMessage(tptr->id, FAULT_BREAKNUM); + } + } + tptr = tptr->tlnext; + } +} + +#endif diff --git a/lib/ultralib/src/rmon/rmoncmds.c b/lib/ultralib/src/rmon/rmoncmds.c new file mode 100644 index 0000000..a2bee99 --- /dev/null +++ b/lib/ultralib/src/rmon/rmoncmds.c @@ -0,0 +1,49 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "rmonint.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +static int NotImplemented(KKHeader* dummy UNUSED) { + return TV_ERROR_ILLEGAL_CALL; +} + +static FUNPTR dispatchTable[] = { + __rmonLoadProgram, __rmonListProcesses, __rmonGetExeName, __rmonListThreads, + __rmonThreadStatus, NotImplemented, __rmonStopThread, __rmonRunThread, + NotImplemented, NotImplemented, __rmonSetFault, NotImplemented, + __rmonGetRegionCount, __rmonGetRegions, __rmonGetGRegisters, __rmonSetGRegisters, + __rmonGetFRegisters, __rmonSetFRegisters, __rmonReadMem, __rmonWriteMem, + __rmonSetBreak, __rmonClearBreak, __rmonListBreak, NotImplemented, + NotImplemented, NotImplemented, NotImplemented, NotImplemented, + NotImplemented, NotImplemented, __rmonSetComm, NotImplemented, + NotImplemented, NotImplemented, NotImplemented, NotImplemented, + NotImplemented, NotImplemented, NotImplemented, NotImplemented, + NotImplemented, NotImplemented, NotImplemented, NotImplemented, + NotImplemented, NotImplemented, NotImplemented, NotImplemented, + NotImplemented, __rmonGetSRegs, __rmonSetSRegs, __rmonGetVRegs, + __rmonSetVRegs, NotImplemented, +}; + +int __rmonExecute(KKHeader* request) { + int retval; + KKHeader reply; + + if (request->code >= ARRLEN(dispatchTable) - 1) { + return TV_ERROR_ILLEGAL_CALL; + } + + retval = dispatchTable[(int)request->code](request); + if (retval < TV_ERROR_NO_ERROR) { + reply.code = request->code; + reply.error = retval; + __rmonSendReply(&reply, sizeof(reply), KK_TYPE_REPLY); + } + return retval; +} + +#endif diff --git a/lib/ultralib/src/rmon/rmonint.h b/lib/ultralib/src/rmon/rmonint.h new file mode 100644 index 0000000..350b779 --- /dev/null +++ b/lib/ultralib/src/rmon/rmonint.h @@ -0,0 +1,169 @@ +#ifndef _RMONINT_H +#define _RMONINT_H + +#include "dbgproto.h" +#include "PR/os_internal.h" + +/* mips */ + +#define MIPS_LWC2_OPCODE 50 +#define MIPS_SWC2_OPCODE 58 + +#define MIPS_LW_OPCODE 35 +#define MIPS_SW_OPCODE 43 + +#define MIPS_BREAK_OPCODE 0xD +#define MIPS_BREAK_MASK 0xFC00003F + +#define MIPS_BREAK(code) \ + ((((code) & 0xFFFFF) << 6) | MIPS_BREAK_OPCODE) + +/* R4300 General Purpose Register Indices */ +#define GREG_IDX_ZERO 0 +#define GREG_IDX_AT 1 +#define GREG_IDX_T9 25 +#define GREG_IDX_K0 26 +#define GREG_IDX_GP 28 +#define GREG_IDX_RA 31 +#define GREG_IDX_LO 32 +#define GREG_IDX_HI 33 +#define GREG_IDX_CAUSE 34 +#define GREG_IDX_PC 35 +#define GREG_IDX_SR 36 + +/* RSP Scalar Register Indices */ +#define SREG_IDX_ZERO 0 +#define SREG_IDX_RA 31 +#define SREG_IDX_DRAM_ADDR (32 + 0) +#define SREG_IDX_MEM_ADDR (32 + 1) +#define SREG_IDX_RD_LEN (32 + 2) +#define SREG_IDX_PC (32 + 3) +#define SREG_IDX_WR_LEN (32 + 4) +#define SREG_IDX_STATUS (32 + 5) +#define SREG_IDX_DMA_FULL (32 + 6) +#define SREG_IDX_DMA_BUSY (32 + 7) + +/* RSP Vector Register Properties */ +#define VREG_NUM 32 +#define VREG_SIZE 0x10 + +/* rmon */ + +#define RMON_MESG_CPU_BREAK 2 +#define RMON_MESG_SP_BREAK 4 +#define RMON_MESG_FAULT 8 + +#define RMON_CPU 0 +#define RMON_RSP 1 + +/* "thread id" for rsp */ +#define RMON_TID_RSP 1000 +/* "thread priority" for rsp */ +#define RMON_PRI_RSP 42 + +/* "thread id" for no thread running */ +#define RMON_TID_NOTHREAD 1003 + +#define RMON_PID_CPU 1002 +#define RMON_PID_RSP 1001 + +/* Largest serviceable read/write memory request */ +#define RMON_MAX_XFER_SIZE 1024 + +/* rmonmain */ + +void __rmonSendHeader(KKHeader* const block, u32 blockSize, u32 type); +void __rmonSendReply(KKHeader* const block, u32 blockSize, u32 replyType); +void __rmonSendData(char* const block, unsigned int blockSize); + +extern int __rmonActive; + +/* rmonmisc */ + +void __rmonInit(void); +void __rmonPanic(void); + +extern OSMesgQueue __rmonMQ; + +/* rmonmem */ + +void __rmonWriteWordTo(u32* addr, u32 val); +u32 __rmonReadWordAt(u32* addr); +void __rmonMemcpy(u8* dest, u8* srce, u32 count); +void __rmonCopyWords(u32* dest, u32* srce, u32 count); + +extern u8 __rmonUtilityBuffer[256]; + +/* rmonsio */ + +void __rmonSendFault(OSThread* thread); +void __rmonIOflush(void); +void __rmonIOputw(u32 word); +void __rmonIOhandler(void); + +extern void* __osRdb_DbgRead_Buf; +extern u8 rmonRdbReadBuf[]; + +/* rmonrcp */ + +int __rmonRCPrunning(void); +void __rmonIdleRCP(void); +void __rmonStepRCP(void); +void __rmonRunRCP(void); + +/* rmonbrk */ + +u32 __rmonGetBranchTarget(int method, int thread, char* addr); +int __rmonSetSingleStep(int thread, u32* instptr); +void __rmonGetExceptionStatus(KKStatusEvent* reply); +void __rmonHitBreak(void); +void __rmonHitSpBreak(void); +void __rmonHitCpuFault(void); + +extern u8 __rmonRcpAtBreak; + +/* rmonregs */ + +u32 __rmonGetRegisterContents(int method, int threadNumber, int regNumber); + +/* rmontask */ + +void __rmonMaskIdleThreadInts(void); +OSThread* __rmonGetTCB(int threadNumber); +int __rmonStopUserThreads(int whichThread); +int __rmonGetThreadStatus(int method, int id, KKStatusEvent* reply); + +/* rmoncmds */ + +int __rmonExecute(KKHeader* request); + +/* commands */ + +typedef int (*FUNPTR)(); + +int __rmonLoadProgram(KKHeader* req); +int __rmonListProcesses(KKHeader* req); +int __rmonGetExeName(KKHeader* req); +int __rmonListThreads(KKHeader* req); +int __rmonThreadStatus(KKHeader* req); +int __rmonStopThread(KKHeader* req); +int __rmonRunThread(KKHeader* req); +int __rmonSetFault(KKHeader* req); +int __rmonGetRegionCount(KKHeader* req); +int __rmonGetRegions(KKHeader* req); +int __rmonGetGRegisters(KKHeader* req); +int __rmonSetGRegisters(KKHeader* req); +int __rmonGetFRegisters(KKHeader* req); +int __rmonSetFRegisters(KKHeader* req); +int __rmonReadMem(KKHeader* req); +int __rmonWriteMem(KKHeader* req); +int __rmonSetBreak(KKHeader* req); +int __rmonClearBreak(KKHeader* req); +int __rmonListBreak(KKHeader* req); +int __rmonSetComm(KKHeader* req); +int __rmonGetSRegs(KKHeader* req); +int __rmonSetSRegs(KKHeader* req); +int __rmonGetVRegs(KKHeader* req); +int __rmonSetVRegs(KKHeader* req); + +#endif diff --git a/lib/ultralib/src/rmon/rmonmain.c b/lib/ultralib/src/rmon/rmonmain.c new file mode 100644 index 0000000..6e2ee6d --- /dev/null +++ b/lib/ultralib/src/rmon/rmonmain.c @@ -0,0 +1,127 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "PR/os_internal.h" +#include "rmonint.h" +#include "PR/rcp.h" +#include "sptask.h" +#include "PR/rdb.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +int __rmonActive = FALSE; + +static vu32 somethingToDo; +static u32 inbuffer[280] ALIGNED(0x10); +static u8 cmdinptr; +static u8 cmdoutptr; +static int state; +static char* inPointer; + +void __rmonSendHeader(KKHeader* const block, u32 blockSize, u32 type) { + int sent; + char* cPtr = (char*)block; + + block->rev = KK_REV; + block->type = type; + + sent = 0; + while (sent < blockSize) { + sent += __osRdbSend(cPtr + sent, blockSize - sent, RDB_TYPE_GtoH_DEBUG); + } +} + +void __rmonSendReply(KKHeader* const block, u32 blockSize, u32 replyType) { + char* cPtr; + int sent = 0; + + block->length = blockSize; + cPtr = (char*)&blockSize; + + /* send size */ + while (sent < (signed)sizeof(blockSize)) { + sent += __osRdbSend(cPtr + sent, sizeof(blockSize) - sent, RDB_TYPE_GtoH_DEBUG); + } + + /* send data */ + __rmonSendHeader(block, blockSize, replyType); + __rmonIOflush(); +} + +void __rmonSendData(char* const block, unsigned int blockSize) { + int* blockPointer = (int*)block; + unsigned int wordCount = (u32)(blockSize + 3) / 4; + u32 data; + union { + char bufBytes[4]; + u32 bufWord; + } buffer; + + if (((u32)block & 3) == 0) { + while (wordCount--) { + if ((u32)blockPointer >= SP_DMEM_START && (u32)blockPointer < 0x05000000) { + __osSpRawReadIo((u32)blockPointer++, &data); + __rmonIOputw(data); + } else { + __rmonIOputw(*(blockPointer++)); + } + } + } else while (wordCount--) { + __rmonMemcpy((u8*)buffer.bufBytes, (u8*)blockPointer, sizeof(buffer)); + __rmonIOputw(buffer.bufWord); + blockPointer++; + } + __rmonIOflush(); +} + +void rmonMain(void) { + register int newChars UNUSED; + + STUBBED_PRINTF(("rmon: Thread %d created\n")); + STUBBED_PRINTF(("rmon: Thread %d destroyed\n")); + + somethingToDo = 0; + cmdoutptr = 0; + cmdinptr = 0; + + __rmonInit(); + __rmonActive = TRUE; + + state = 0; + newChars = 0; + inPointer = (void*)&inbuffer; + + for (;;) { + OSMesg work; + + osRecvMesg(&__rmonMQ, &work, OS_MESG_BLOCK); + + somethingToDo |= (u32)work; + + if (somethingToDo & RMON_MESG_CPU_BREAK) { + somethingToDo &= ~RMON_MESG_CPU_BREAK; + __rmonHitBreak(); + } + if (somethingToDo & RMON_MESG_SP_BREAK) { + somethingToDo &= ~RMON_MESG_SP_BREAK; + __rmonHitSpBreak(); + } + if (somethingToDo & RMON_MESG_FAULT) { + somethingToDo &= ~RMON_MESG_FAULT; + __rmonHitCpuFault(); + } + if (somethingToDo & 0x10) { + somethingToDo; + somethingToDo &= 0xEF; + } + if (somethingToDo & 0x20) { + somethingToDo; + somethingToDo &= 0xDF; + } + } +} + +#endif diff --git a/lib/ultralib/src/rmon/rmonmem.c b/lib/ultralib/src/rmon/rmonmem.c new file mode 100644 index 0000000..3a8a3ab --- /dev/null +++ b/lib/ultralib/src/rmon/rmonmem.c @@ -0,0 +1,271 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "PR/sptask.h" +#include "rmonint.h" +#include "PR/rdb.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +u8 __rmonUtilityBuffer[256] ALIGNED(8); + +void __rmonWriteWordTo(u32* addr, u32 val) { + while (__osSpRawWriteIo((u32)addr, val) != 0) { + ; + } +} + +u32 __rmonReadWordAt(u32* addr) { + u32 data; + + if (addr >= (u32*)SP_DMEM_START && addr < (u32*)0x05000000) { + __osSpRawReadIo((u32)addr, &data); + return data; + } + return 0; +} + +void __rmonMemcpy(u8* dest, u8* srce, u32 count) { + while (count--) { + *dest++ = *srce++; + } +} + +void __rmonCopyWords(u32* dest, u32* srce, u32 count) { + while (count--) { + *dest++ = *srce++; + } +} + +static void strcpy(char* dest, char* srce) { + while ((*dest++ = *srce++)) { + ; + } +} + +int __rmonReadMem(KKHeader* req) { + char* cPtr; + int sent; + int dataSize; + KKReadRequest* request = (KKReadRequest*)req; + KKBufferEvent* reply = (KKBufferEvent*)__rmonUtilityBuffer; + u8* blockStart; + + STUBBED_PRINTF(("ReadMem @ %08x for %d\n", request->addr, request->nbytes)); + + reply->header.code = request->header.code; + reply->object = request->object; + reply->header.error = TV_ERROR_NO_ERROR; + + if (request->addr == (u32)-1) { + return TV_ERROR_INVALID_ADDRESS; + } + if (request->nbytes > RMON_MAX_XFER_SIZE) { + return TV_ERROR_INVALID_CAPABILITY; + } + + if (req->method == RMON_RSP) { + if ((request->addr < SP_IMEM_START || (request->addr + request->nbytes) > SP_IMEM_END)) { + if ((request->addr < SP_DMEM_START || (request->addr + request->nbytes) > SP_DMEM_END)) { + return TV_ERROR_INVALID_ADDRESS; + } + } + } else if (osVirtualToPhysical((void*)request->addr) == (u32)-1) { + return TV_ERROR_INVALID_ADDRESS; + } + + blockStart = (u8*)request->addr; + reply->header.length = request->nbytes + sizeof(reply->header) + sizeof(reply->object); + dataSize = request->nbytes + sizeof(reply->header) + sizeof(reply->object); + + cPtr = (char*)&dataSize; + sent = 0; + while (sent < (signed)sizeof(dataSize)) { + sent += __osRdbSend(cPtr + sent, sizeof(dataSize) - sent, RDB_TYPE_GtoH_DEBUG); + } + + __rmonSendHeader(&reply->header, sizeof(reply->header) + sizeof(reply->object), KK_TYPE_REPLY); + __rmonSendData(blockStart, request->nbytes); + return TV_ERROR_NO_ERROR; +} + +int __rmonWriteMem(KKHeader* req) { + register KKWriteRequest* request = (KKWriteRequest*)req; + KKObjectEvent reply; + + STUBBED_PRINTF(("WriteMem\n")); + + /* Bad virtual address, abort */ + if (req->method == RMON_CPU && osVirtualToPhysical((u32*)request->writeHeader.addr) == (u32)-1) { + return TV_ERROR_INVALID_ADDRESS; + } + + /* Transfer size too large, abort */ + if (request->writeHeader.nbytes > RMON_MAX_XFER_SIZE) { + return TV_ERROR_INVALID_CAPABILITY; + } + + if ((request->writeHeader.addr >= SP_DMEM_START && (request->writeHeader.addr + request->writeHeader.nbytes) < 0x05000000)) { + int align; + u32 word; + + if ((align = request->writeHeader.addr & 3) != 0) { + STUBBED_PRINTF(("Long unaligned write...\n")); + + if (request->writeHeader.nbytes != 1) { + return TV_ERROR_INVALID_ADDRESS; + } + + /* Unaligned write; read the word, substitute in the written byte, write it back */ + word = __rmonReadWordAt((u32*)(request->writeHeader.addr & ~3)); + if (align == 1) { + word = (word & ~0xFF0000) | (request->buffer[0] << 0x10); + } else if (align == 2) { + word = (word & ~0xFF00) | (request->buffer[0] << 8); + } else { + word = (word & ~0xFF) | (request->buffer[0] << 0); + } + __rmonWriteWordTo((u32*)(request->writeHeader.addr & ~3), word); + } else { + int wordCount = request->writeHeader.nbytes / sizeof(u32); + u32* wordPointer = (u32*)request->buffer; + + if (request->writeHeader.nbytes % sizeof(u32) != 0) { + STUBBED_PRINTF(("RCP write not an integral number of words\n")); + return TV_ERROR_INVALID_ADDRESS; + } + + while (wordCount--) { + __rmonWriteWordTo((u32*)request->writeHeader.addr, *(wordPointer++)); + request->writeHeader.addr += sizeof(*wordPointer); + } + } + } else { + __rmonMemcpy((u8*)request->writeHeader.addr, (u8*)request->buffer, request->writeHeader.nbytes); + } + + reply.header.code = request->writeHeader.header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->writeHeader.object; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + + return TV_ERROR_NO_ERROR; +} + +int __rmonListProcesses(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKObjsEvent reply; + + STUBBED_PRINTF(("ListProcesses\n")); + + reply.object = 0; + reply.objs.number = 1; + reply.objs.objects[0] = (req->method == RMON_RSP) ? RMON_PID_RSP : RMON_PID_CPU; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonLoadProgram(KKHeader* request UNUSED) { + STUBBED_PRINTF(("LoadProgram\n")); + + return TV_ERROR_ILLEGAL_CALL; +} + +int __rmonGetExeName(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKBufferEvent* reply = (KKBufferEvent*)__rmonUtilityBuffer; + + STUBBED_PRINTF(("GetExeName\n")); + + reply->header.code = request->header.code; + reply->header.error = TV_ERROR_NO_ERROR; + reply->object = request->object; + + if (req->method == RMON_RSP) { + strcpy(reply->buffer, "imem"); + } else { + strcpy(reply->buffer, "rmon"); + } + __rmonSendReply(&reply->header, sizeof(reply->header) + sizeof(reply->object) + 8, KK_TYPE_REPLY); + + return TV_ERROR_NO_ERROR; +} + +int __rmonGetRegionCount(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKNumberEvent reply; + + STUBBED_PRINTF(("GetRegionCount\n")); + + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->object; + + reply.number = (req->method == RMON_RSP) ? 2 : 5; + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + + return TV_ERROR_NO_ERROR; +} + +int __rmonGetRegions(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKRegionEvent* reply = (KKRegionEvent*)__rmonUtilityBuffer; + int numRegions; + + STUBBED_PRINTF(("GetRegions\n")); + + numRegions = (req->method == RMON_RSP) ? 2 : 6; + + reply->header.length = numRegions * sizeof(reply->regions[0]) + sizeof(*reply); + reply->header.code = request->header.code; + reply->header.error = TV_ERROR_NO_ERROR; + reply->object = request->object; + reply->number = numRegions; + + reply->regions[1].vaddr = SP_IMEM_START; + reply->regions[1].size = SP_IMEM_END + 1 - SP_IMEM_START; + reply->regions[1].flags = 1 | 2 | 4; + reply->regions[1].paddr = SP_IMEM_START; + + reply->regions[0].vaddr = SP_DMEM_START; + reply->regions[0].size = SP_DMEM_END + 1 - SP_DMEM_START; + reply->regions[0].flags = 1 | 2; + reply->regions[0].paddr = SP_DMEM_START; + + if (numRegions > 2) { + reply->regions[2].vaddr = 0x88200000; + reply->regions[2].size = 0x6130; + reply->regions[2].flags = 1 | 4; + reply->regions[2].paddr = 0; + + reply->regions[3].vaddr = 4; + reply->regions[3].size = 0x200000; + reply->regions[3].flags = 1 | 2; + reply->regions[3].paddr = 0; + + reply->regions[4].vaddr = 0x4002000; + reply->regions[4].size = 0x800000; + reply->regions[4].flags = 1 | 2; + reply->regions[4].paddr = 0; + + reply->regions[5].vaddr = 0x88206130; + reply->regions[5].size = 0x9000; + reply->regions[5].flags = 1 | 2; + reply->regions[5].paddr = 0; + } + + __rmonSendReply(&reply->header, reply->header.length, KK_TYPE_REPLY); + + return TV_ERROR_NO_ERROR; +} + +#endif diff --git a/lib/ultralib/src/rmon/rmonmisc.c b/lib/ultralib/src/rmon/rmonmisc.c new file mode 100644 index 0000000..0f9c4cd --- /dev/null +++ b/lib/ultralib/src/rmon/rmonmisc.c @@ -0,0 +1,69 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "PR/os_internal.h" +#include "PR/sptask.h" +#include "rmonint.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +OSMesgQueue __rmonMQ ALIGNED(8); + +int __rmonSetFault(KKHeader* req) { + KKFaultRequest* request = (KKFaultRequest*)req; + KKObjectEvent reply; + + STUBBED_PRINTF(("SetFault\n")); + + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->tid; + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +static OSThread rmonIOThread ALIGNED(8); +static OSMesg rmonMsgs[8] ALIGNED(8); +static u64 rmonIOStack[2048] ALIGNED(8); +static OSMesg rmonPiMsgs[8] ALIGNED(8); +static OSMesgQueue rmonPiMQ ALIGNED(8); + +void __rmonInit(void) { + osCreateMesgQueue(&__rmonMQ, rmonMsgs, ARRLEN(rmonMsgs)); + osSetEventMesg(OS_EVENT_CPU_BREAK, &__rmonMQ, (OSMesg)RMON_MESG_CPU_BREAK); + osSetEventMesg(OS_EVENT_SP_BREAK, &__rmonMQ, (OSMesg)RMON_MESG_SP_BREAK); + osSetEventMesg(OS_EVENT_FAULT, &__rmonMQ, (OSMesg)RMON_MESG_FAULT); + osSetEventMesg(OS_EVENT_THREADSTATUS, &__rmonMQ, NULL); + osCreateThread(&rmonIOThread, 0, (void (*)(void*))__rmonIOhandler, NULL, + rmonIOStack + ARRLEN(rmonIOStack), OS_PRIORITY_MAX); + osCreatePiManager(OS_PRIORITY_PIMGR, &rmonPiMQ, rmonPiMsgs, ARRLEN(rmonPiMsgs)); + osStartThread(&rmonIOThread); +} + +void __rmonPanic(void) { + STUBBED_PRINTF(("PANIC!!\n")); + + for (;;) { + ; + } +} + +int __rmonSetComm(KKHeader* req) { + KKObjectEvent reply; + + STUBBED_PRINTF(("SetComm\n")); + + reply.header.code = req->code; + reply.object = 0; + reply.header.error = TV_ERROR_NO_ERROR; + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + + return TV_ERROR_NO_ERROR; +} + +#endif diff --git a/lib/ultralib/src/rmon/rmonprint.c b/lib/ultralib/src/rmon/rmonprint.c new file mode 100644 index 0000000..8ac91a5 --- /dev/null +++ b/lib/ultralib/src/rmon/rmonprint.c @@ -0,0 +1 @@ +/* Empty file */ diff --git a/lib/ultralib/src/rmon/rmonrcp.s b/lib/ultralib/src/rmon/rmonrcp.s new file mode 100644 index 0000000..2128c9a --- /dev/null +++ b/lib/ultralib/src/rmon/rmonrcp.s @@ -0,0 +1,59 @@ +#ifndef _FINALROM + +#include "sys/asm.h" +#include "sys/regdef.h" +#include "PR/rcp.h" +#include "PR/R4300.h" + +.text + +/* check if the rsp is currently running by polling HALT or BROKE bits in SP_STATUS */ +LEAF(__rmonRCPrunning) + move v0, zero + lw t0, PHYS_TO_K1(SP_STATUS_REG) + and t0, SP_STATUS_HALT | SP_STATUS_BROKE + bnez t0, isHalted + ori v0, 1 +isHalted: + jr ra +END(__rmonRCPrunning) + +/* stop the rsp, first wait for any ongoing dma to complete before setting HALT in SP_STATUS */ +LEAF(__rmonIdleRCP) + li a0, PHYS_TO_K1(SP_DMA_BUSY_REG) +wait4dma: + lw v0, (a0) + bnez v0, wait4dma + li a1, SP_CLR_INTR_BREAK | SP_SET_HALT + li a0, PHYS_TO_K1(SP_STATUS_REG) + sw a1, (a0) + +/* wait for the rsp to stop */ +awaitIdle: + li a0, PHYS_TO_K1(SP_STATUS_REG) + lw v0, (a0) + and v0, SP_STATUS_HALT | SP_STATUS_BROKE + beqz v0, awaitIdle + jr ra +END(__rmonIdleRCP) + +/* run the rsp in single-step mode to step one instruction */ +LEAF(__rmonStepRCP) + li a0, PHYS_TO_K1(SP_STATUS_REG) + li a1, SP_CLR_INTR_BREAK | SP_SET_SSTEP | SP_CLR_BROKE | SP_CLR_HALT + sw a1, (a0) + b awaitIdle +END(__rmonStepRCP) + +/* run the rsp normally */ +LEAF(__rmonRunRCP) + li a0, PHYS_TO_K1(MI_INTR_MASK_REG) + li a1, MI_INTR_MASK_SET_SP + sw a1, (a0) + li a0, PHYS_TO_K1(SP_STATUS_REG) + li a1, SP_SET_INTR_BREAK | SP_CLR_SSTEP | SP_CLR_BROKE | SP_CLR_HALT + sw a1, (a0) + jr ra +END(__rmonRunRCP) + +#endif diff --git a/lib/ultralib/src/rmon/rmonregs.c b/lib/ultralib/src/rmon/rmonregs.c new file mode 100644 index 0000000..d1e3af2 --- /dev/null +++ b/lib/ultralib/src/rmon/rmonregs.c @@ -0,0 +1,402 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "PR/sptask.h" +#include "rmonint.h" +#include "PR/rdb.h" + +#include "macros.h" + +// TODO: these come from headers +#ident "$Revision: 1.4 $" +#ident "$Revision: 3.70 $" +#ident "$Revision: 1.5 $" +#ident "$Revision: 1.2 $" +#ident "$Revision: 1.4 $" + +static u32 RCPpc; +static u32 oldIMEMvalue; +static u32 DMEMbuffer[4]; + +typedef union { + u32 everything; + struct { + int opcode : 6; + int base : 5; + int rt : 5; + int offset : 16; + } scalarop; + struct { + int opcode : 6; + int base : 5; + int rt : 5; + int size : 5; + int element : 4; + int offset : 7; + } vectorop; +} INSTRUCTION; + +static void LoadStoreSU(int opcode, int regno) { + INSTRUCTION inst; + + /* Prepare a scalar load or store instruction at DMEM address 0 */ + inst.everything = 0; + inst.scalarop.opcode = opcode; + inst.scalarop.rt = regno; + __rmonWriteWordTo((u32*)SP_IMEM_START, inst.everything); + __rmonWriteWordTo((u32*)SP_PC_REG, 0); +} + +static void LoadStoreVU(int opcode, int regno) { + INSTRUCTION inst; + + /* Prepare a vector 128-bit load or store instruction at DMEM address 0 */ + inst.everything = 0; + inst.vectorop.opcode = opcode; + inst.vectorop.rt = regno; + inst.vectorop.size = 4; /* LQV / SQV */ + __rmonWriteWordTo((u32*)SP_IMEM_START, inst.everything); + __rmonWriteWordTo((u32*)SP_PC_REG, 0); +} + +static void SetUpForRCPop(int isVector) { + /* Save RSP data that would be overwritten when reading or writing registers */ + RCPpc = __rmonReadWordAt((u32*)SP_PC_REG); + oldIMEMvalue = __rmonReadWordAt((u32*)SP_IMEM_START); + DMEMbuffer[0] = __rmonReadWordAt((u32*)SP_DMEM_START); + if (isVector) { + DMEMbuffer[1] = __rmonReadWordAt((u32*)(SP_DMEM_START + 0x4)); + DMEMbuffer[2] = __rmonReadWordAt((u32*)(SP_DMEM_START + 0x8)); + DMEMbuffer[3] = __rmonReadWordAt((u32*)(SP_DMEM_START + 0xC)); + } +} + +static void CleanupFromRCPop(int isVector) { + /* Restore RSP data that was saved to read or write registers */ + __rmonWriteWordTo((u32*)SP_DMEM_START, DMEMbuffer[0]); + if (isVector) { + __rmonWriteWordTo((u32*)(SP_DMEM_START + 0x4), DMEMbuffer[1]); + __rmonWriteWordTo((u32*)(SP_DMEM_START + 0x8), DMEMbuffer[2]); + /* BUG: the last word is not restored properly */ + __rmonWriteWordTo((u32*)(SP_DMEM_START + 0xC), DMEMbuffer[2]); + } + __rmonWriteWordTo((u32*)SP_IMEM_START, oldIMEMvalue); + __rmonWriteWordTo((u32*)SP_PC_REG, RCPpc); +} + +int __rmonGetGRegisters(KKHeader* req) { + register KKObjectRequest* request = (KKObjectRequest*)req; + KKGregEvent reply; + + STUBBED_PRINTF(("GetGRegisters\n")); + + reply.tid = request->object; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + + if (request->header.method == RMON_CPU) { + OSThread* tptr = __rmonGetTCB(request->object); + u64* tcbregptr; + register s32 i; + + if (tptr == NULL) { + return TV_ERROR_INVALID_ID; + } + + for (i = GREG_IDX_AT, tcbregptr = &tptr->context.at; i < GREG_IDX_K0; i++, tcbregptr++) { + reply.registers.gregs[i] = *tcbregptr; + } + for (i = GREG_IDX_GP, tcbregptr = &tptr->context.gp; i < GREG_IDX_CAUSE; i++, tcbregptr++) { + reply.registers.gregs[i] = *tcbregptr; + } + + reply.registers.gregs[GREG_IDX_CAUSE] = tptr->context.cause; + reply.registers.gregs[GREG_IDX_PC] = tptr->context.pc; + reply.registers.gregs[GREG_IDX_SR] = tptr->context.sr; + reply.registers.gregs[GREG_IDX_ZERO] = 0; + } else { + return TV_ERROR_INVALID_ID; + } + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonSetGRegisters(KKHeader* req) { + register KKGRegsetRequest* request = (KKGRegsetRequest*)req; + KKObjectEvent reply; + + STUBBED_PRINTF(("SetGRegisters\n")); + + if (request->header.method == RMON_CPU) { + OSThread* tptr = __rmonGetTCB(request->tid); + u64* tcbregptr; + register int i; + + if (tptr == NULL) { + return TV_ERROR_INVALID_ID; + } + + for (i = GREG_IDX_AT, tcbregptr = &tptr->context.at; i < GREG_IDX_K0; i++, tcbregptr++) { + *tcbregptr = (s32)request->registers.gregs[i]; + } + + for (i = GREG_IDX_GP, tcbregptr = &tptr->context.gp; i < GREG_IDX_CAUSE; i++, tcbregptr++) { + *tcbregptr = (s32)request->registers.gregs[i]; + } + + tptr->context.cause = request->registers.gregs[GREG_IDX_CAUSE]; + tptr->context.pc = request->registers.gregs[GREG_IDX_PC]; + tptr->context.sr = request->registers.gregs[GREG_IDX_SR]; + } else { + return TV_ERROR_INVALID_ID; + } + + reply.object = request->tid; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonGetFRegisters(KKHeader* req) { + register KKObjectRequest* request = (KKObjectRequest*)req; + KKFPregEvent reply; + OSThread* tptr; + volatile float f UNUSED; + + STUBBED_PRINTF(("GetFRegisters\n")); + + if (req->method != RMON_CPU) { + return TV_ERROR_INVALID_ID; + } + + /* touch fpu to ensure registers are saved to the context structure */ + f = 0.0f; + + tptr = __rmonGetTCB(request->object); + if (tptr == NULL) { + return TV_ERROR_INVALID_ID; + } + + __rmonCopyWords((u32*)reply.registers.fpregs.regs, (u32*)&tptr->context.fp0, ARRLEN(reply.registers.fpregs.regs)); + + reply.registers.fpcsr = tptr->context.fpcsr; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.tid = request->object; + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; + +} + +int __rmonSetFRegisters(KKHeader* req) { + register KKFPRegsetRequest* request = (KKFPRegsetRequest*)req; + KKObjectEvent reply; + OSThread* tptr; + volatile float f UNUSED; + + STUBBED_PRINTF(("SetFRegisters\n")); + + if (req->method != RMON_CPU) { + return TV_ERROR_INVALID_ID; + } + + /* touch fpu to ensure registers are saved to the context structure */ + f = 0.0f; + + tptr = __rmonGetTCB(request->tid); + if (tptr == NULL) { + return TV_ERROR_INVALID_ID; + } + + __rmonCopyWords((u32*)&tptr->context.fp0, (u32*)request->registers.fpregs.regs, ARRLEN(request->registers.fpregs.regs)); + tptr->context.fpcsr = request->registers.fpcsr; + + reply.object = request->tid; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +static u32 rmonGetRcpRegister(int regNumber) { + u32 contents; + + if (__rmonRCPrunning()) { + return 0; + } + + SetUpForRCPop(FALSE); + LoadStoreSU(MIPS_SW_OPCODE, regNumber); + __rmonStepRCP(); + contents = __rmonReadWordAt((u32*)SP_DMEM_START); + CleanupFromRCPop(FALSE); + + return contents; + +} + +int __rmonGetSRegs(KKHeader* req) { + register KKObjectRequest* request = (KKObjectRequest*)req; + KKCpSregEvent reply; + register int i; + + STUBBED_PRINTF(("GetSRegisters\n")); + + if (__rmonRCPrunning()) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + + reply.tid = request->object; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + + SetUpForRCPop(FALSE); + for (i = SREG_IDX_ZERO; i <= SREG_IDX_RA; i++) { + LoadStoreSU(MIPS_SW_OPCODE, i); + __rmonStepRCP(); + reply.registers.sregs[i] = __rmonReadWordAt((u32*)SP_DMEM_START); + } + CleanupFromRCPop(FALSE); + + reply.registers.sregs[SREG_IDX_DRAM_ADDR] = __rmonReadWordAt((u32*)SP_DRAM_ADDR_REG); + reply.registers.sregs[SREG_IDX_MEM_ADDR] = __rmonReadWordAt((u32*)SP_MEM_ADDR_REG); + reply.registers.sregs[SREG_IDX_RD_LEN] = __rmonReadWordAt((u32*)SP_RD_LEN_REG); + reply.registers.sregs[SREG_IDX_PC] = __rmonReadWordAt((u32*)SP_PC_REG) + SP_IMEM_START; + reply.registers.sregs[SREG_IDX_WR_LEN] = __rmonReadWordAt((u32*)SP_WR_LEN_REG); + reply.registers.sregs[SREG_IDX_STATUS] = __rmonReadWordAt((u32*)SP_STATUS_REG); + reply.registers.sregs[SREG_IDX_DMA_FULL] = __rmonReadWordAt((u32*)SP_DMA_FULL_REG); + reply.registers.sregs[SREG_IDX_DMA_BUSY] = __rmonReadWordAt((u32*)SP_DMA_BUSY_REG); + + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonSetSRegs(KKHeader* req) { + register KKCpScalarRegsetRequest* request = (KKCpScalarRegsetRequest*)req; + KKObjectEvent reply; + register int i; + + STUBBED_PRINTF(("SetSRegisters\n")); + + if (__rmonRCPrunning()) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + + SetUpForRCPop(FALSE); + for (i = SREG_IDX_ZERO; i <= SREG_IDX_RA; i++) { + __rmonWriteWordTo((u32*)SP_DMEM_START, request->registers.sregs[i]); + LoadStoreSU(MIPS_LW_OPCODE, i); + __rmonStepRCP(); + } + CleanupFromRCPop(FALSE); + + __rmonWriteWordTo((u32*)SP_DRAM_ADDR_REG, request->registers.sregs[SREG_IDX_DRAM_ADDR]); + __rmonWriteWordTo((u32*)SP_MEM_ADDR_REG, request->registers.sregs[SREG_IDX_MEM_ADDR]); + __rmonWriteWordTo((u32*)SP_PC_REG, request->registers.sregs[SREG_IDX_PC] & 0xFFF); + __rmonWriteWordTo((u32*)SP_WR_LEN_REG, request->registers.sregs[SREG_IDX_WR_LEN]); + __rmonWriteWordTo((u32*)SP_STATUS_REG, request->registers.sregs[SREG_IDX_STATUS]); + + reply.object = request->tid; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonGetVRegs(KKHeader* req) { + char* cPtr; + int sent; + int dataSize; + register KKObjectRequest* request = (KKObjectRequest*)req; + KKCpVregEvent reply; + register int i; + + STUBBED_PRINTF(("GetVRegisters\n")); + + if (__rmonRCPrunning()) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + + reply.tid = request->object; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.header.length = sizeof(reply); + + dataSize = sizeof(reply); + cPtr = (char*)&dataSize; + sent = 0; + while (sent < (signed)sizeof(dataSize)) { + sent += __osRdbSend(cPtr + sent, sizeof(dataSize) - sent, RDB_TYPE_GtoH_DEBUG); + } + + __rmonSendHeader(&reply.header, VREG_SIZE, KK_TYPE_REPLY); + + SetUpForRCPop(TRUE); + for (i = 0; i < VREG_NUM; i++) { + LoadStoreVU(MIPS_SWC2_OPCODE, i); + __rmonStepRCP(); + __rmonSendData((void*)SP_DMEM_START, VREG_SIZE); + } + CleanupFromRCPop(TRUE); + + return TV_ERROR_NO_ERROR; +} + +int __rmonSetVRegs(KKHeader* req) { + register KKCpVectorRegsetRequest* request = (KKCpVectorRegsetRequest*)req; + KKObjectEvent reply; + register int i; + + STUBBED_PRINTF(("SetVRegs\n")); + + if (__rmonRCPrunning()) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + + SetUpForRCPop(TRUE); + for (i = 0; i < VREG_NUM; i++) { + __rmonCopyWords((u32*)SP_DMEM_START, (u32*)&request->registers.vregs[i], VREG_SIZE / sizeof(u32)); + LoadStoreVU(MIPS_LWC2_OPCODE, i); + __rmonStepRCP(); + } + CleanupFromRCPop(TRUE); + + reply.object = request->tid; + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +u32 __rmonGetRegisterContents(int method, int threadNumber, int regNumber) { + if (method == RMON_CPU) { + /* CPU register */ + u32* regPointer; + OSThread* tptr; + + if (regNumber >= GREG_IDX_AT && regNumber < GREG_IDX_K0) { + regNumber -= GREG_IDX_AT - GREG_IDX_ZERO; + } else if (regNumber >= GREG_IDX_GP && regNumber < GREG_IDX_LO) { + regNumber -= GREG_IDX_GP - GREG_IDX_T9; + } else { + return 0; + } + tptr = __rmonGetTCB(threadNumber); + if (tptr == NULL) { + return 0; + } + regPointer = (u32*)&tptr->context; + regPointer += regNumber; + return *regPointer; + } else { + /* RSP register */ + return rmonGetRcpRegister(regNumber); + } +} + +#endif diff --git a/lib/ultralib/src/rmon/rmonsio.c b/lib/ultralib/src/rmon/rmonsio.c new file mode 100644 index 0000000..ffeca17 --- /dev/null +++ b/lib/ultralib/src/rmon/rmonsio.c @@ -0,0 +1,77 @@ +#ifndef _FINALROM + +#include "PR/os_internal.h" +#include "PR/ultraerror.h" +#include "PR/ultralog.h" +#include "PR/sptask.h" +#include "dbgproto.h" +#include "rmonint.h" +#include "PR/ramrom.h" +#include "PR/rdb.h" +#include "PR/rmon.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +static OSMesgQueue IOmq; +static OSMesg IOmsgs; + +void* __osRdb_DbgRead_Buf; +u8 rmonRdbReadBuf[RMON_DBG_BUF_SIZE] ALIGNED(0x10); + +void __rmonSendFault(OSThread* thread) { + volatile float f UNUSED; + u8* tPtr; + u32 sent = 0; + + /* touch fpu to ensure registers are saved to the context structure */ + f = 0.0f; + + tPtr = (u8*)thread; + while (sent < sizeof(OSThread)) { + sent += __osRdbSend(tPtr + sent, sizeof(OSThread) - sent, RDB_TYPE_GtoH_FAULT); + } +} + +void __rmonIOflush(void) { + int sent = 0; + char tstr[4]; + + while (sent <= 0) { + sent += __osRdbSend(tstr, 1, RDB_TYPE_GtoH_DEBUG_DONE); + } +} + +void __rmonIOputw(u32 word) { + int sent = 0; + char* cPtr = (char*)&word; + + while (sent < 4) { + sent += __osRdbSend(cPtr + sent, sizeof(word) - sent, RDB_TYPE_GtoH_DEBUG); + } +} + +void __rmonIOhandler(void) { + int sent; + char tstr[4]; + + osCreateMesgQueue(&IOmq, &IOmsgs, 1); + osSetEventMesg(OS_EVENT_RDB_DBG_DONE, &IOmq, NULL); + __osRdb_DbgRead_Buf = rmonRdbReadBuf; + + while (TRUE) { + osRecvMesg(&IOmq, NULL, OS_MESG_BLOCK); + + __rmonExecute((KKHeader*)&rmonRdbReadBuf); + __osRdb_DbgRead_Buf = rmonRdbReadBuf; + + sent = 0; + while (sent <= 0) { + sent += __osRdbSend(tstr, 1, RDB_TYPE_GtoH_DEBUG_READY); + } + } +} + +#endif diff --git a/lib/ultralib/src/rmon/rmontask.c b/lib/ultralib/src/rmon/rmontask.c new file mode 100644 index 0000000..8728374 --- /dev/null +++ b/lib/ultralib/src/rmon/rmontask.c @@ -0,0 +1,332 @@ +#ifndef _FINALROM + +#include "dbgproto.h" +#include "PR/os_internal.h" +#include "rmonint.h" +#include "PR/rcp.h" +#include "sptask.h" + +#include "macros.h" + +// TODO: this comes from a header +#ident "$Revision: 1.4 $" + +void __rmonMaskIdleThreadInts(void) { + register OSThread* tptr = __osGetActiveQueue(); + + while (tptr->priority != -1) { + if (tptr->priority == OS_PRIORITY_IDLE) { + tptr->context.sr &= ~OS_IM_CPU; + tptr->context.sr |= (OS_IM_RDBREAD | OS_IM_RDBWRITE | OS_IM_CART); + break; + } + tptr = tptr->tlnext; + } +} + +OSThread* __rmonGetTCB(int threadNumber) { + register OSThread* tptr = __osGetActiveQueue(); + + if (threadNumber < 1) { + return NULL; + } + + while (tptr->priority != -1) { + if (tptr->id == threadNumber) { + return tptr; + } + tptr = tptr->tlnext; + } + + return NULL; +} + +int __rmonStopUserThreads(int whichThread) { + register int whichOne = 0; + register OSThread* tptr = __osGetActiveQueue(); + + STUBBED_PRINTF(("StopThreads %d\n", whichThread)); + + if (whichThread != 0) { + /* Stop specified thread */ + + while (tptr->priority != -1) { + if (tptr->id == whichThread) { + break; + } + tptr = tptr->tlnext; + } + + if (tptr->priority == -1) { + return 0; + } + + if (tptr->priority > OS_PRIORITY_IDLE && tptr->priority <= OS_PRIORITY_APPMAX) { + osStopThread(tptr); + if (tptr->state != OS_STATE_STOPPED) { + STUBBED_PRINTF(("Couldn't stop thread %d\n", tptr->id)); + } + whichOne = whichThread; + } + } else { + /* Stop all threads */ + + while (tptr->priority != -1) { + if (tptr->priority > OS_PRIORITY_IDLE && tptr->priority <= OS_PRIORITY_APPMAX) { + osStopThread(tptr); + if (tptr->state != OS_STATE_STOPPED) { + STUBBED_PRINTF(("Couldn\'t stop thread %d\n", tptr->id)); + } + whichOne = -1; + } + tptr = tptr->tlnext; + } + } + return whichOne; +} + +int __rmonListThreads(KKHeader* req) { + register KKObjectRequest* request = (KKObjectRequest*)req; + KKObjsEvent* reply = (KKObjsEvent*)__rmonUtilityBuffer; + + STUBBED_PRINTF(("ListThreads\n")); + + reply->object = (request->object == -1) ? RMON_PID_CPU : request->object; + + if (req->method == RMON_RSP) { + reply->objs.number = 1; + reply->objs.objects[0] = RMON_TID_RSP; + } else { + register OSThread* tptr = __osGetActiveQueue(); + + reply->objs.number = 0; + + while (tptr->priority != -1) { + if (tptr->id != 0) { + reply->objs.objects[reply->objs.number] = tptr->id; + reply->objs.number++; + } + tptr = tptr->tlnext; + } + } + reply->header.code = request->header.code; + reply->header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply->header, sizeof(*reply) + sizeof(reply->objs.objects[0]) * (reply->objs.number - 1), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonGetThreadStatus(int method, int id, KKStatusEvent* reply) { + u32 inst; + + STUBBED_PRINTF(("ThreadStatus %d method %d\n", id, method)); + + reply->status.tid = id; + reply->status.pid = (method == RMON_RSP) ? RMON_PID_RSP : RMON_PID_CPU; + reply->status.why = 1; + reply->status.what = 0; + reply->status.info.major = 0; + reply->status.info.minor = 0; + reply->status.rv = 0; + + if (method == RMON_RSP) { + reply->status.start = SP_IMEM_START; + reply->status.priority = RMON_PRI_RSP; + + if (__rmonRCPrunning()) { + reply->status.flags = OS_STATE_RUNNING; + /* Cannot read RSP PC or current instruction while the RSP is running */ + reply->status.info.addr = 0; + reply->status.instr = 0; + } else { + reply->status.flags = OS_STATE_STOPPED; + reply->status.info.addr = __rmonReadWordAt((u32*)SP_PC_REG) + SP_IMEM_START; + inst = __rmonReadWordAt((u32*)reply->status.info.addr); + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + inst = MIPS_BREAK_OPCODE; + } + if (__rmonRcpAtBreak) { + /* Report RSP break */ + reply->status.why = 2; + reply->status.info.major = 2; + reply->status.info.minor = 4; + } + reply->status.instr = inst; + } + } else { + OSThread* tptr = __osGetActiveQueue(); + + while (tptr->priority != -1) { + if (tptr->id == id) { + break; + } + tptr = tptr->tlnext; + } + if (tptr->priority == -1) { + return TV_ERROR_INVALID_ID; + } + + reply->status.priority = tptr->priority; + reply->status.flags = (tptr->state != 0) ? tptr->state : OS_STATE_STOPPED; + reply->status.info.addr = tptr->context.pc; + + inst = *(u32*)(tptr->context.pc); + if ((inst & MIPS_BREAK_MASK) == MIPS_BREAK_OPCODE) { + inst = MIPS_BREAK_OPCODE; + } + + reply->status.instr = inst; + reply->status.start = (int)tptr; + + if (tptr->flags & OS_FLAG_CPU_BREAK) { + /* Report break */ + reply->status.why = 2; + reply->status.info.major = 2; + reply->status.info.minor = 4; + } else if (tptr->flags & OS_FLAG_FAULT) { + /* Report fault */ + reply->status.why = 2; + reply->status.info.major = 1; + reply->status.info.minor = 2; + } + } + + return TV_ERROR_NO_ERROR; +} + +int __rmonThreadStatus(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKStatusEvent reply; + + if (__rmonGetThreadStatus(req->method, request->object, &reply) != TV_ERROR_NO_ERROR) { + return TV_ERROR_INVALID_ID; + } + + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + return TV_ERROR_NO_ERROR; +} + +int __rmonStopThread(KKHeader* req) { + KKObjectRequest* request = (KKObjectRequest*)req; + KKStatusEvent reply; + u32* pc; + + STUBBED_PRINTF(("StopThread %d\n", request->object)); + + switch (req->method) { + case RMON_CPU: + __rmonStopUserThreads(request->object); + break; + case RMON_RSP: + if (__rmonRCPrunning()) { + /* Stop the rsp */ + __rmonIdleRCP(); + pc = (u32*)__rmonReadWordAt((u32*)SP_PC_REG); + if (pc == NULL) { + break; + } + pc--; + /* Check if the RSP is stopped in a branch delay slot, if it is step out of it. The RSP would otherwise + lose information about whether the branch should or should not be taken when reading registers. */ + if (__rmonGetBranchTarget(RMON_RSP, RMON_TID_RSP, (void*)((u32)pc + SP_IMEM_START)) % 4 == 0) { + __rmonStepRCP(); + } + } + break; + default: + return TV_ERROR_OPERATIONS_PROTECTED; + } + + if (__rmonGetThreadStatus(req->method, request->object, &reply) != TV_ERROR_NO_ERROR) { + return TV_ERROR_INVALID_ID; + } + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + if (reply.status.flags == OS_STATE_STOPPED) { + reply.header.code = KK_CODE_THREAD_STATUS; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_EXCEPTION); + } + return TV_ERROR_NO_ERROR; + +} + +int __rmonRunThread(KKHeader* req) { + KKRunThreadRequest* request = (KKRunThreadRequest*)req; + KKObjectEvent reply; + KKStatusEvent exceptionReply; + register OSThread* tptr; + register int runNeeded = FALSE; + + STUBBED_PRINTF(("RunThread %d\n", request->tid)); + + switch (req->method) { + case RMON_CPU: + tptr = __osGetActiveQueue(); + while (tptr->priority != -1) { + if (tptr->id == request->tid) { + break; + } + tptr = tptr->tlnext; + } + + if (tptr->priority == -1) { + return TV_ERROR_INVALID_ID; + } + if (tptr->state != OS_STATE_STOPPED) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + tptr->flags &= ~(OS_FLAG_CPU_BREAK | OS_FLAG_FAULT); + if (request->actions.flags & KK_RUN_SETPC) { + tptr->context.pc = request->actions.vaddr; + } + if ((request->actions.flags & KK_RUN_SSTEP) && !__rmonSetSingleStep(request->tid, (u32*)tptr->context.pc)) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + runNeeded = TRUE; + break; + case RMON_RSP: + if (__rmonRCPrunning()) { + return TV_ERROR_OPERATIONS_PROTECTED; + } + if (request->actions.flags & KK_RUN_SETPC) { + __rmonWriteWordTo((u32*)SP_PC_REG, request->actions.vaddr - SP_IMEM_START); + } + if (request->actions.flags & KK_RUN_SSTEP) { + /* If the RSP is stopped at a branch step twice so as to not stop in a branch delay slot. */ + if (__rmonGetBranchTarget(RMON_RSP, RMON_TID_RSP, (void*)(__rmonReadWordAt((u32*)SP_PC_REG) + SP_IMEM_START)) % 4 == 0) { + __rmonStepRCP(); + } + __rmonStepRCP(); + __rmonRcpAtBreak = TRUE; + } else { + __rmonRcpAtBreak = FALSE; + __rmonRunRCP(); + } + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->tid; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + if (request->actions.flags & KK_RUN_SSTEP) { + __rmonGetThreadStatus(RMON_RSP, RMON_TID_RSP, &exceptionReply); + __rmonGetExceptionStatus(&exceptionReply); + __rmonSendReply(&exceptionReply.header, sizeof(exceptionReply), KK_TYPE_EXCEPTION); + } + return TV_ERROR_NO_ERROR; + default: + return TV_ERROR_OPERATIONS_PROTECTED; + } + + reply.header.code = request->header.code; + reply.header.error = TV_ERROR_NO_ERROR; + reply.object = request->tid; + __rmonSendReply(&reply.header, sizeof(reply), KK_TYPE_REPLY); + + if (runNeeded) { + osStartThread(tptr); + } + return 1; +} + +#endif diff --git a/lib/ultralib/src/sched/Makefile b/lib/ultralib/src/sched/Makefile new file mode 100644 index 0000000..d4cd659 --- /dev/null +++ b/lib/ultralib/src/sched/Makefile @@ -0,0 +1,19 @@ +#!smake +# +# Makefile for the scheduler subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + + +# LCOPTS = -mips2 -non_shared -fullwarn -G 0 +LCINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include + +CFILES = \ + sched.c + +OBJECTS = $(CFILES:.c=.o) + +default: $(OBJECTS) + +include $(COMMONRULES) diff --git a/lib/ultralib/src/sched/sched.c b/lib/ultralib/src/sched/sched.c new file mode 100644 index 0000000..7cf59dd --- /dev/null +++ b/lib/ultralib/src/sched/sched.c @@ -0,0 +1,623 @@ +/*==================================================================== + * + * Copyright 1995, 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 <ultralog.h> +#include <assert.h> +#include <sched.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +/* + * private typedefs and defines + */ +#define VIDEO_MSG 666 +#define RSP_DONE_MSG 667 +#define RDP_DONE_MSG 668 +#define PRE_NMI_MSG 669 + +/* + * OSScTask state + */ +#define OS_SC_DP 0x0001 /* set if still needs dp */ +#define OS_SC_SP 0x0002 /* set if still needs sp */ +#define OS_SC_YIELD 0x0010 /* set if yield requested */ +#define OS_SC_YIELDED 0x0020 /* set if yield completed */ + +/* + * OSScTask->flags type identifier + */ +#define OS_SC_XBUS (OS_SC_SP | OS_SC_DP) +#define OS_SC_DRAM (OS_SC_SP | OS_SC_DP | OS_SC_DRAM_DLIST) +#define OS_SC_DP_XBUS (OS_SC_SP) +#define OS_SC_DP_DRAM (OS_SC_SP | OS_SC_DRAM_DLIST) +#define OS_SC_SP_XBUS (OS_SC_DP) +#define OS_SC_SP_DRAM (OS_SC_DP | OS_SC_DRAM_DLIST) + +/* + * private functions + */ +static void __scMain(void *arg); +static void __scHandleRetrace(OSSched *s); +static void __scHandleRSP(OSSched *s); +static void __scHandleRDP(OSSched *s); + +static void __scAppendList(OSSched *s, OSScTask *t); +OSScTask *__scTaskReady(OSScTask *t); +static s32 __scTaskComplete(OSSched *s,OSScTask *t); +static void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp); +static void __scYield(OSSched *s); +static s32 __scSchedule(OSSched *sc, OSScTask **sp, OSScTask **dp, + s32 availRCP); + + +/* +#define SC_LOGGING 1 +*/ + + +#ifdef SC_LOGGING +#define SC_LOG_LEN 32*1024 +static OSLog scLog; +static OSLog *l = &scLog; +static u32 logArray[SC_LOG_LEN/sizeof(u32)]; +#endif + +/*********************************************************************** + * Scheduler API + **********************************************************************/ +void osCreateScheduler(OSSched *sc, void *stack, OSPri priority, + u8 mode, u8 numFields) +{ + sc->curRSPTask = 0; + sc->curRDPTask = 0; + sc->clientList = 0; + sc->frameCount = 0; + sc->audioListHead = 0; + sc->gfxListHead = 0; + sc->audioListTail = 0; + sc->gfxListTail = 0; + sc->retraceMsg.type = OS_SC_RETRACE_MSG; /* sent to apps */ + sc->prenmiMsg.type = OS_SC_PRE_NMI_MSG; + + osCreateMesgQueue(&sc->interruptQ, sc->intBuf, OS_SC_MAX_MESGS); + osCreateMesgQueue(&sc->cmdQ, sc->cmdMsgBuf, OS_SC_MAX_MESGS); + + /* + * Set up video manager, listen for Video, RSP, and RDP interrupts + */ + osCreateViManager(OS_PRIORITY_VIMGR); + osViSetMode(&osViModeTable[mode]); + osViBlack(TRUE); + osSetEventMesg(OS_EVENT_SP, &sc->interruptQ, (OSMesg)RSP_DONE_MSG); + osSetEventMesg(OS_EVENT_DP, &sc->interruptQ, (OSMesg)RDP_DONE_MSG); + osSetEventMesg(OS_EVENT_PRENMI, &sc->interruptQ, (OSMesg)PRE_NMI_MSG); + + osViSetEvent(&sc->interruptQ, (OSMesg)VIDEO_MSG, numFields); + +#ifdef SC_LOGGING + osCreateLog(l, logArray, sizeof(logArray)); +#endif + + osCreateThread(&sc->thread, 4, __scMain, (void *)sc, stack, priority); + osStartThread(&sc->thread); +} + +/* + * Add a client to the scheduler. Clients receive messages at retrace time + */ +void osScAddClient(OSSched *sc, OSScClient *c, OSMesgQueue *msgQ) +{ + OSIntMask mask; + + mask = osSetIntMask(OS_IM_NONE); + + c->msgQ = msgQ; + c->next = sc->clientList; + sc->clientList = c; + + osSetIntMask(mask); +} + +void osScRemoveClient(OSSched *sc, OSScClient *c) +{ + OSScClient *client = sc->clientList; + OSScClient *prev = 0; + OSIntMask mask; + + mask = osSetIntMask(OS_IM_NONE); + + while (client != 0) { + if (client == c) { + if(prev) + prev->next = c->next; + else + sc->clientList = c->next; + break; + } + prev = client; + client = client->next; + } + + osSetIntMask(mask); +} + +OSMesgQueue *osScGetCmdQ(OSSched *sc) +{ + return &sc->cmdQ; +} + +/*********************************************************************** + * Scheduler implementation + **********************************************************************/ +static void __scMain(void *arg) +{ + OSMesg msg; + OSSched *sc = (OSSched *)arg; + OSScClient *client; + static int count = 0; + + while (1) { + + osRecvMesg(&sc->interruptQ, (OSMesg *)&msg, OS_MESG_BLOCK); + +#ifdef SC_LOGGING + if (++count % 1024 == 0) + osFlushLog(l); +#endif + + + switch ((int) msg) { + case (VIDEO_MSG): + __scHandleRetrace(sc); + break; + + case (RSP_DONE_MSG): + __scHandleRSP(sc); + break; + + case (RDP_DONE_MSG): + __scHandleRDP(sc); + break; + + case (PRE_NMI_MSG): + /* + * notify audio and graphics threads to fade out + */ + for (client = sc->clientList;client != 0;client = client->next) { + osSendMesg(client->msgQ, (OSMesg) &sc->prenmiMsg, + OS_MESG_NOBLOCK); + } + break; + } + } +} + +/* + * scHandleRetrace() + */ +static int dp_busy = 0; +static int dpCount = 0; + +void __scHandleRetrace(OSSched *sc) +{ + OSScTask *rspTask; + OSScClient *client; + s32 i; + s32 state; + OSScTask *sp = 0; + OSScTask *dp = 0; + + sc->frameCount++; + +#ifdef SC_LOGGING + osLogEvent(l, 500, 4, sc->frameCount, sc->curRSPTask, sc->curRDPTask); +#endif + + /* + * Read the task command queue and schedule tasks + */ + while (osRecvMesg(&sc->cmdQ, (OSMesg *)&rspTask, OS_MESG_NOBLOCK) != -1) { + __scAppendList(sc, rspTask); + } + + if (sc->doAudio && sc->curRSPTask) { + /* + * Preempt the running gfx task. Note: if the RSP + * component of the graphics task has finished, but the + * RDP component is still running, we can start an audio + * task which will freeze the RDP (and save the RDP cmd + * FIFO) while the audio RSP code is running. + */ + __scYield(sc); + } else { + state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); + if ( __scSchedule (sc, &sp, &dp, state) != state) + __scExec(sc, sp, dp); + } + + /* + * notify audio and graphics threads to start building the command + * lists for the next frame (client threads may choose not to + * build the list in overrun case) + */ + for (client = sc->clientList; client != 0; client = client->next) { + osSendMesg(client->msgQ, (OSMesg) &sc->retraceMsg, OS_MESG_NOBLOCK); + } +} + +/* + * __scHandleRSP is called when an RSP task signals that it has + * finished or yielded (at the hosts request) + */ +void __scHandleRSP(OSSched *sc) +{ + OSScTask *t, *sp = 0, *dp = 0; + s32 state; + + + assert(sc->curRSPTask); + + t = sc->curRSPTask; + sc->curRSPTask = 0; + +#ifdef SC_LOGGING + osLogEvent(l, 510, 3, t, t->state, t->flags); +#endif + + if ((t->state & OS_SC_YIELD) && osSpTaskYielded(&t->list)) { + t->state |= OS_SC_YIELDED; +#ifndef _FINALROM + t->totalTime += osGetTime() - t->startTime; +#endif + if ((t->flags & OS_SC_TYPE_MASK) == OS_SC_XBUS) { + /* push the task back on the list */ + t->next = sc->gfxListHead; + sc->gfxListHead = t; + if (sc->gfxListTail == 0) + sc->gfxListTail = t; + } + +#ifdef SC_LOGGING + osLogEvent(l, 521, 1, t); +#endif + + } else { + t->state &= ~OS_SC_NEEDS_RSP; + __scTaskComplete(sc, t); + } + + state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); + if ( (__scSchedule (sc, &sp, &dp, state)) != state) + __scExec(sc, sp, dp); +} + +/* + * __scHandleRDP is called when an RDP task signals that it has + * finished + */ +void __scHandleRDP(OSSched *sc) +{ + OSScTask *t, *sp = 0, *dp = 0; + s32 state; + + assert(sc->curRDPTask); + assert(sc->curRDPTask->list.t.type == M_GFXTASK); + + t = sc->curRDPTask; + sc->curRDPTask = 0; + +#ifdef SC_LOGGING + osLogEvent(l, 515, 3, t, t->state, t->flags); +#endif + + t->state &= ~OS_SC_NEEDS_RDP; + + __scTaskComplete(sc, t); + + state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); + if ( (__scSchedule (sc, &sp, &dp, state)) != state) + __scExec(sc, sp, dp); +} + +/* + * __scTaskReady checks to see if the graphics task is able to run + * based on the current state of the RCP. + */ +OSScTask *__scTaskReady(OSScTask *t) +{ + int rv = 0; + void *a; + void *b; + + if (t) { + /* + * If there is a pending swap bail out til later (next + * retrace). + */ + if ((a=osViGetCurrentFramebuffer()) != (b=osViGetNextFramebuffer())) { +#ifdef SC_LOGGING + osLogEvent(l, 513, 2, a, b); +#endif + return 0; + } + + return t; + } + + return 0; +} + +/* + * __scTaskComplete checks to see if the task is complete (all RCP + * operations have been performed) and sends the done message to the + * client if it is. + */ +s32 __scTaskComplete(OSSched *sc, OSScTask *t) +{ + int rv; + static int firsttime = 1; + + if ((t->state & OS_SC_RCP_MASK) == 0) { /* none of the needs bits set */ + + assert (t->msgQ); + +#ifndef _FINALROM + t->totalTime += osGetTime() - t->startTime; +#endif + +#ifdef SC_LOGGING + osLogEvent(l, 504, 1, t); +#endif + rv = osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK); + + if (t->list.t.type == M_GFXTASK) { + if ((t->flags & OS_SC_SWAPBUFFER) && (t->flags & OS_SC_LAST_TASK)){ + if (firsttime) { + osViBlack(FALSE); + firsttime = 0; + } + osViSwapBuffer(t->framebuffer); +#ifdef SC_LOGGING + osLogEvent(l, 525, 1, t->framebuffer); +#endif + } + } + return 1; + } + + return 0; +} + +/* + * Place task on either the audio or graphics queue + */ +void __scAppendList(OSSched *sc, OSScTask *t) +{ + long type = t->list.t.type; + + assert ( (type == M_AUDTASK) || (type == M_GFXTASK)); + + if (type == M_AUDTASK) { + if (sc->audioListTail) + sc->audioListTail->next = t; + else + sc->audioListHead = t; + + sc->audioListTail = t; + sc->doAudio = 1; +#ifdef SC_LOGGING + osLogEvent(l, 506, 1, t); +#endif + } else { + if (sc->gfxListTail) + sc->gfxListTail->next = t; + else + sc->gfxListHead = t; + + sc->gfxListTail = t; +#ifdef SC_LOGGING + osLogEvent(l, 507, 1, t); +#endif + } + + t->next = NULL; + t->state = t->flags & OS_SC_RCP_MASK; +} + +/* + * + */ +void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp) +{ + int rv; + +#ifdef SC_LOGGING + osLogEvent(l, 511, 2, sp, dp); +#endif + + assert(sc->curRSPTask == 0); + + if (sp) { + if (sp->list.t.type == M_AUDTASK) { + osWritebackDCacheAll(); /* flush the cache */ + } + + sp->state &= ~(OS_SC_YIELD | OS_SC_YIELDED); +#ifndef _FINALROM + sp->startTime = osGetTime(); +#endif + osSpTaskLoad(&sp->list); + osSpTaskStartGo(&sp->list); + sc->curRSPTask = sp; + if (sp == dp) + sc->curRDPTask = dp; + } + + if (dp && (dp != sp)) { + assert(dp->list.t.output_buff); + +#ifdef SC_LOGGING + osLogEvent(l, 523, 3, dp, dp->list.t.output_buff, + (u32)*dp->list.t.output_buff_size); +#endif + rv = osDpSetNextBuffer(dp->list.t.output_buff, + *dp->list.t.output_buff_size); + + dp_busy = 1; + dpCount = 0; + + assert(rv == 0); + + sc->curRDPTask = dp; + } +} + +static void __scYield(OSSched *sc) +{ + +#ifdef SC_LOGGING + osLogEvent(l, 503, 1, sc->curRSPTask ); +#endif + + if (sc->curRSPTask->list.t.type == M_GFXTASK) { + +/* assert(sc->curRSPTask->state & OS_SC_YIELD);*/ + + sc->curRSPTask->state |= OS_SC_YIELD; + + osSpTaskYield(); + } else { +#ifdef SC_LOGGING + osLogEvent(l, 508, 1, sc->curRSPTask); +#endif + } +} + +/* + * Schedules the tasks to be run on the RCP + */ +s32 __scSchedule(OSSched *sc, OSScTask **sp, OSScTask **dp, s32 availRCP) +{ + s32 avail = availRCP; + OSScTask *gfx = sc->gfxListHead; + OSScTask *audio = sc->audioListHead; + +#ifdef SC_LOGGING + osLogEvent(l, 517, 3, *sp, *dp, availRCP); +#endif + + if (sc->doAudio && (avail & OS_SC_SP)) { + + if (gfx && (gfx->flags & OS_SC_PARALLEL_TASK)) { + *sp = gfx; + avail &= ~OS_SC_SP; + } else { + *sp = audio; + avail &= ~OS_SC_SP; + sc->doAudio = 0; + sc->audioListHead = sc->audioListHead->next; + if (sc->audioListHead == NULL) + sc->audioListTail = NULL; + } + } else { +#ifdef SC_LOGGING + osLogEvent(l, 520, 1, gfx); +#endif + if (__scTaskReady(gfx)) { + +#ifdef SC_LOGGING + osLogEvent(l, 522, 3, gfx, gfx->state, gfx->flags); +#endif + switch (gfx->flags & OS_SC_TYPE_MASK) { + case (OS_SC_XBUS): + if (gfx->state & OS_SC_YIELDED) { +#ifdef SC_LOGGING + osLogEvent(l, 518, 0); +#endif + /* can hit this if RDP finishes at yield req */ + /* assert(gfx->state & OS_SC_DP); */ + + if (avail & OS_SC_SP) { /* if SP is available */ +#ifdef SC_LOGGING + osLogEvent(l, 519, 0); +#endif + *sp = gfx; + avail &= ~OS_SC_SP; + + if (gfx->state & OS_SC_DP) { /* if it needs DP */ + *dp = gfx; + avail &= ~OS_SC_DP; + + if (avail & OS_SC_DP == 0) + assert(sc->curRDPTask == gfx); + + } + + sc->gfxListHead = sc->gfxListHead->next; + if (sc->gfxListHead == NULL) + sc->gfxListTail = NULL; + + } + } else { + if (avail == (OS_SC_SP | OS_SC_DP)) { + *sp = *dp = gfx; + avail &= ~(OS_SC_SP | OS_SC_DP); + sc->gfxListHead = sc->gfxListHead->next; + if (sc->gfxListHead == NULL) + sc->gfxListTail = NULL; + } + } + + break; + + case (OS_SC_DRAM): + case (OS_SC_DP_DRAM): + case (OS_SC_DP_XBUS): + if (gfx->state & OS_SC_SP) { /* if needs SP */ + if (avail & OS_SC_SP) { /* if SP is available */ + *sp = gfx; + avail &= ~OS_SC_SP; + } + } else if (gfx->state & OS_SC_DP) { /* if needs DP */ + if (avail & OS_SC_DP) { /* if DP available */ + *dp = gfx; + avail &= ~OS_SC_DP; + sc->gfxListHead = sc->gfxListHead->next; + if (sc->gfxListHead == NULL) + sc->gfxListTail = NULL; + } + } + break; + + case (OS_SC_SP_DRAM): + case (OS_SC_SP_XBUS): + default: + break; + } + } + } + + if (avail != availRCP) + avail = __scSchedule(sc, sp, dp, avail); + + return avail; + +} + diff --git a/lib/ultralib/src/sched/sched_log.fmt b/lib/ultralib/src/sched/sched_log.fmt new file mode 100644 index 0000000..50e042d --- /dev/null +++ b/lib/ultralib/src/sched/sched_log.fmt @@ -0,0 +1,19 @@ +500 "__scHandleRetrace: framecount %d, curRSPTask 0x%x, curRDPTask 0x%x" +510 "__scHandleRSP: Current 0x%x state 0x%x flags 0x%x" +521 "__scHandleRSP: Yielded Task 0x%x" +515 "__scHandleRDP: Current 0x%x state 0x%x flags 0x%x" +513 "__scTaskReady: Pending swap bail - current 0x%x next 0x%x" +514 "__scTaskReady: Rendering bail - current 0x%x" +504 "__scTaskComplete: Task 0x%x" +525 "__scTaskComplete: Swapbuffer 0x%x" +506 "__scAppendList: Audio task 0x%x" +507 "__scAppendList: Gfx task 0x%x" +511 "__scExec: sp 0x%x, dp 0x%x" +523 "__scExec: DP only buf 0x%x, size %d" +503 "__scYield: curRSPtask 0x%x" +508 "__scYield: NOT A GFX TASK!! curRSPtask 0x%x" +517 "__scSchedule: sp 0x%x, dp 0x%x, avail 0x%x" +520 "__scSchedule: gfx task 0x%x" +522 "__scSchedule: gfx task ready 0x%x, state 0x%x, flags 0x%x" +518 "__scSchedule: Yielded" +519 "__scSchedule: SP available" diff --git a/lib/ultralib/src/sp/Makefile b/lib/ultralib/src/sp/Makefile new file mode 100644 index 0000000..7807431 --- /dev/null +++ b/lib/ultralib/src/sp/Makefile @@ -0,0 +1,30 @@ +#!smake +# +# Makefile for the sp subdirectory +# + +include $(ROOT)/usr/include/make/PRdefs + + +# LCOPTS = -mips2 -non_shared -fullwarn -G 0 +LCINCS = -I. -I$(ROOT)/usr/include/PR -I$(ROOT)/usr/include + +CFILES = \ + clearattribute.c \ + color.c \ + hide.c \ + setattribute.c \ + show.c \ + sprite.c \ + spriteex.c \ + spriteex2.c \ + spscale.c + + +ASFILES = + +OBJECTS = $(CFILES:.c=.o) + +default: $(OBJECTS) + +include $(COMMONRULES) diff --git a/lib/ultralib/src/sp/clearattribute.c b/lib/ultralib/src/sp/clearattribute.c new file mode 100644 index 0000000..e5faf16 --- /dev/null +++ b/lib/ultralib/src/sp/clearattribute.c @@ -0,0 +1,35 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spClearAttribute() + * + * Clears attributes about a sprite. + */ +void +spClearAttribute (Sprite *sp, s32 attr) +{ + sp->attr &= ~attr; +} diff --git a/lib/ultralib/src/sp/color.c b/lib/ultralib/src/sp/color.c new file mode 100644 index 0000000..a5abc85 --- /dev/null +++ b/lib/ultralib/src/sp/color.c @@ -0,0 +1,39 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spColor() + * + * Sets the color for IA or I images. + */ +void +spColor (Sprite *sp, unsigned char red, unsigned char green, + unsigned char blue, unsigned char alpha) +{ + sp->red = red; + sp->green = green; + sp->blue = blue; + sp->alpha = alpha; +} diff --git a/lib/ultralib/src/sp/hide.c b/lib/ultralib/src/sp/hide.c new file mode 100644 index 0000000..6223c2c --- /dev/null +++ b/lib/ultralib/src/sp/hide.c @@ -0,0 +1,35 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spHide() + * + * Hides a sprite so that it will not be drawn at the next spUpdate(). + */ +void +spHide (Sprite *sp) +{ + spSetAttribute (sp, SP_HIDDEN); +} diff --git a/lib/ultralib/src/sp/setattribute.c b/lib/ultralib/src/sp/setattribute.c new file mode 100644 index 0000000..887df08 --- /dev/null +++ b/lib/ultralib/src/sp/setattribute.c @@ -0,0 +1,35 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spSetAttribute() + * + * Sets attributes about a sprite. + */ +void +spSetAttribute ( Sprite *sp, s32 attr) +{ + sp->attr |= attr; +} diff --git a/lib/ultralib/src/sp/show.c b/lib/ultralib/src/sp/show.c new file mode 100644 index 0000000..dc0db54 --- /dev/null +++ b/lib/ultralib/src/sp/show.c @@ -0,0 +1,35 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spShow() + * + * Shows a sprite so that it will be drawn at the next spUpdate(). + */ +void +spShow (Sprite *sp) +{ + spClearAttribute (sp, SP_HIDDEN); +} diff --git a/lib/ultralib/src/sp/sprite.c b/lib/ultralib/src/sp/sprite.c new file mode 100644 index 0000000..0779f1f --- /dev/null +++ b/lib/ultralib/src/sp/sprite.c @@ -0,0 +1,757 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <assert.h> +#include <sp.h> + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +/* + * spSetZ() + * + */ +void +spSetZ (Sprite *sp, s32 z) +{ + +#ifdef DEBUG + emPrintf("spSetZ (Sprite 0x%08x, (%d))\n", sp, z ); +#endif + + sp->zdepth = (s16)z; +} + +/* + * spMove() + * + * Moves a sprite on the screen. + */ +void +spMove (Sprite *sp, s32 x, s32 y) +{ + +#ifdef DEBUG + emPrintf("spMove (Sprite 0x%08x, (%d,%d))\n", sp, x, y ); +#endif + + sp->x = (s16)x; + sp->y = (s16)y; +} + +static s32 scissor_xmax; +static s32 scissor_ymax; + +static s32 scissor_xmin; +static s32 scissor_ymin; + +/* + * spScissor() + * + * Sets the scissoring box to be used for subsequent Sprite Drawing + */ +void +spScissor (s32 xmin, s32 xmax, s32 ymin, s32 ymax ) +{ + scissor_xmin = xmin; + scissor_ymin = ymin; + + scissor_xmax = xmax; + scissor_ymax = ymax; +} + +static int *prev_bmbuf = NULL; + +/* + * drawbitmap() + * + * Draws a bitmap from a sprite at a location on the screen. If the + * "usevert" flag is set, then the routine will use vertices and triangles + * to draw the bitmap. Otherwise, the texture rectangle instruction + * will be used. + */ + +static void +drawbitmap (Gfx **glp, Sprite *s, Bitmap *b, + s32 x, s32 y, s32 xx, s32 yy, s32 fs, s32 ft, s32 sx, s32 sy) +{ + s32 rs, rt; + s32 rxh, ryh; + s32 rxl, ryl; + Gfx *gl; + s32 tex_width, tex_height; + Gtexrect gt, *g; + s32 s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod; + + g = > + + tex_width = b->width_img; + tex_height= s->bmHreal; + +#ifdef rmDEBUG + rmonPrintf("\tdrawbitmap (buf= 0x%08x; x,y= %d,%d; w,h= %d,%d )\n", + b->buf, x, y, b->width, s->bmheight ); +#endif + gl = *glp; + + /* Scissoring */ + if( (x >= scissor_xmax) || (y >= scissor_ymax) ) { +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Upper Left corner (%d,%d) beyond range (%d,%d)\n", + x, y, scissor_xmax, scissor_ymax ); +#endif + return; + } + + if( (xx < scissor_xmin) || (yy < scissor_ymin) ) { +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Lower Right corner (%d,%d) not in range (%d,%d)\n", + xx, yy, scissor_xmin, scissor_ymin ); +#endif + return; + } + + + if (x < scissor_xmin) { + rxh = scissor_xmin*4; + rs = (b->s<<5) + fs + (((scissor_xmin - x)*sx)>>5); +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Left Edge (%d) not in range (%d,%d)\n", + x, scissor_xmin, scissor_xmax ); +#endif + } else { + rxh = x*4; + rs = (b->s<<5) + fs; + }; + + if (y < scissor_ymin) { + ryh = scissor_ymin*4; + rt = (b->t<<5) + ft + (((scissor_ymin-y)*sy)>>5); +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Top Edge (%d) not in range (%d,%d)\n", + y, scissor_ymin, scissor_ymax ); +#endif + } else { + ryh = y*4; + rt = (b->t<<5) + ft; + } + + if( xx >= scissor_xmax ) { + rxl = scissor_xmax*4; +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Right Edge (%d) not in range (%d,%d)\n", + xx, scissor_xmin, scissor_xmax ); +#endif + } else { + rxl = xx*4; + }; + + if( yy >= scissor_ymax ) { + ryl = scissor_ymax*4; +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: Bottom Edge (%d) not in range (%d,%d)\n", + yy, scissor_ymin, scissor_ymax ); +#endif + } else { + ryl = yy*4; + }; + + s_clamp = G_TX_CLAMP; t_clamp = G_TX_CLAMP; + s_mask = G_TX_NOMASK; t_mask = G_TX_NOMASK; + s_lod = G_TX_NOLOD; t_lod = G_TX_NOLOD; + +#define LOAD_TEX + +#ifdef LOAD_TEX + if( b->buf != prev_bmbuf ) { + switch(s->bmsiz) + { + case G_IM_SIZ_DD: + gDPLoadTextureTile_4b(gl++, b->buf, s->bmfmt, tex_width, tex_height, + b->s, b->t, + b->s + b->width,b->t + b->actualHeight, + 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + break; + case G_IM_SIZ_4b: + if (s->attr & SP_TEXSHUF) { + gDPLoadTextureBlock_4bS(gl++, b->buf, s->bmfmt, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + } else { + gDPLoadTextureBlock_4b(gl++, b->buf, s->bmfmt, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + }; + break; + + case G_IM_SIZ_8b: + if (s->attr & SP_TEXSHUF) { + gDPLoadTextureBlockS(gl++, b->buf, s->bmfmt, G_IM_SIZ_8b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + } else { + gDPLoadTextureBlock(gl++, b->buf, s->bmfmt, G_IM_SIZ_8b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + }; + break; + case G_IM_SIZ_16b: + if (s->bmfmt == G_IM_FMT_YUV ) { + if (s->attr & SP_TEXSHUF) { + gDPLoadTextureBlockYuvS(gl++, b->buf, s->bmfmt, G_IM_SIZ_16b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + } else { + if( b->LUToffset != 0 ) { /* Split Y and UV areas */ + unsigned char *uv, *addr; + int j; + s32 tmem, siz; + + gDPSetTextureImage( gl++, G_IM_FMT_I, G_IM_SIZ_8b, 1, b->buf); + gDPSetTile( gl++, G_IM_FMT_I, G_IM_SIZ_8b, 0, 256, G_TX_LOADTILE, 0, + t_clamp, t_mask, t_lod, + s_clamp, s_mask, s_lod ); + gDPLoadSync( gl++ ); + gDPLoadBlock( gl++, G_TX_LOADTILE, 0,0, tex_width*tex_height -1, + CALC_DXT(tex_width,1) ); + gDPLoadSync( gl++ ); + + uv = ((unsigned char *)b->buf) + + ((tex_width*tex_height)/2)*b->LUToffset; + + for( j=0; j<=(tex_height/2); j++ ) { + addr = uv + ((tex_height/2) -2 -j)*tex_width; + siz = 3*tex_width; + tmem = (tex_width/8)*(tex_height - 2 - 2*j); + if( tmem < 0 ) { + addr += (-tmem)*8; + siz -= (-tmem)*8; + tmem = 0; + }; + if( j == 0 ) + siz = 2*tex_width; + + gDPSetTextureImage( gl++, G_IM_FMT_I, G_IM_SIZ_8b, 1, addr); + gDPSetTile( gl++, G_IM_FMT_I, G_IM_SIZ_8b, 0, tmem, + G_TX_LOADTILE, 0, + t_clamp, t_mask, t_lod, + s_clamp, s_mask, s_lod ); + gDPLoadSync( gl++ ); + gDPLoadBlock( gl++, G_TX_LOADTILE, 0,0, siz -1, + CALC_DXT(tex_width,1) ); + gDPLoadSync( gl++ ); + }; + + gDPSetTile( gl++, s->bmfmt, G_IM_SIZ_16b, (((tex_width) * 1)+7)>>3, 0, + G_TX_RENDERTILE, 0, + t_clamp, t_mask, t_lod, + s_clamp, s_mask, s_lod ); + gDPSetTileSize( gl++, G_TX_RENDERTILE, 0, 0, + ((tex_width)-1) << G_TEXTURE_IMAGE_FRAC, + ((tex_height)-1) << G_TEXTURE_IMAGE_FRAC ); + + } else { + gDPLoadTextureBlockYuv(gl++, b->buf, s->bmfmt, G_IM_SIZ_16b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + }; + }; + } else { + if (s->attr & SP_TEXSHUF) { + gDPLoadTextureBlockS(gl++, b->buf, s->bmfmt, G_IM_SIZ_16b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + } else { + gDPLoadTextureBlock(gl++, b->buf, s->bmfmt, G_IM_SIZ_16b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + }; + }; + break; + case G_IM_SIZ_32b: + if (s->attr & SP_TEXSHUF) { + gDPLoadTextureBlockS(gl++, b->buf, s->bmfmt, G_IM_SIZ_32b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + } else { + gDPLoadTextureBlock(gl++, b->buf, s->bmfmt, G_IM_SIZ_32b, + tex_width, tex_height, 0, + s_clamp, t_clamp, + s_mask, t_mask, + s_lod, t_lod); + }; + break; + } + prev_bmbuf = b->buf; + } +#endif /* LOAD_TEX */ + + + g->cmd = G_TEXRECT; + g->tile = 0; + + g->xh = rxh; + g->xl = rxl; + g->yh = ryh; + g->yl = ryl; + + g->s = rs; + g->t = rt; + + if ((s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + g->dsdx = sx * 4; + else + g->dsdx = sx; + + g->dtdy = sy; + +#ifdef rmDEBUG + rmonPrintf("\trect (xh,l= %d,%d, yh,l= %d,%d, s,t= %d,%d, dsdx=%d, dtdy=%d )\n", + rxh,rxl,ryh,ryl,rs,rt,g->dsdx,sy ); +#endif + + gSPTextureRectangle(gl++,g->xh,g->yh,g->xl,g->yl,g->tile,g->s,g->t,g->dsdx,g->dtdy); + + gDPPipeSync(gl++); + + *glp = gl; +} + +static u16 sp_attr = 0; + +void +spInit( Gfx **glistp ) +{ + Gfx *gl; + + gl = *glistp; + +#ifdef DEBUG + emPrintf("spInit ()\n" ); +#endif + sp_attr = 0; + + scissor_xmin = 0; + scissor_ymin = 0; + + scissor_xmax = 320; + scissor_ymax = 240; + + /* Turn on texturing */ + gDPPipeSync ( gl++ ); + gDPSetCycleType ( gl++, G_CYC_1CYCLE); + gSPTexture ( gl++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON); + gDPSetAlphaCompare ( gl++, G_AC_NONE ); + gDPSetTexturePersp ( gl++, G_TP_NONE ); + gDPSetTextureFilter ( gl++, G_TF_BILERP ); + gDPSetTextureConvert( gl++, G_TC_FILT ); + gDPSetTextureDetail ( gl++, G_TD_CLAMP ); + gDPSetTextureLOD ( gl++, G_TL_TILE ); + gDPSetTextureLUT ( gl++, G_TT_NONE ); + +#define SPRITE_SURF G_RM_TEX_EDGE +#define SPRITE_SURF2 G_RM_TEX_EDGE2 + + gDPSetRenderMode( gl++, SPRITE_SURF, SPRITE_SURF2); + + *glistp = gl; +} + + +/* + * spDraw() + * + * Draws all of the sprites that are associated with bitmaps and that + * are supposed to be drawn (spDraw()). They are drawn from 0 to maxsp, + * so sprites with higher numbers will overwrite lower-numbered sprites. + * + */ +Gfx * +spDraw ( Sprite *s ) +{ + int i; + s32 x, y; + float sx, sy; + Bitmap *b; + Gfx *gl; +#ifndef NDEBUG + Gfx *ogl; +#endif + Gfx *dl_start; + s32 isx, isy; + s32 tx, ty; + s32 tx2, ty2; + s32 x2, y2; + float ftx, fty; + s32 fs, ft; + s32 ex, ey; + +#ifdef rmDEBUG + rmonPrintf("spDraw (Sprite 0x%08x )\n", s ); +#endif + + if (s->attr & SP_HIDDEN) + return(NULL); + + prev_bmbuf = NULL; + + gl = s->rsp_dl_next; + if( gl == NULL ) + gl = s->rsp_dl; + dl_start = gl; + +#ifndef NDEBUG + ogl = gl; +#endif + + b = s->bitmap; + ex = 0; + ey = 0; + + if (sp_attr & SP_EXTERN) /* previous attr was extern? */ + sp_attr = ~s->attr; /* Assume previous modes are all different + from new ones */ + + if (s->attr & SP_EXTERN) /* current attr is extern? */ + sp_attr = s->attr; /* Assume all settings should remain the same */ + + if (s->attr != sp_attr) { + if ((s->attr & SP_TRANSPARENT) && !(sp_attr & SP_TRANSPARENT)) { + gDPSetRenderMode( gl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + } else if (!(s->attr & SP_TRANSPARENT) && + (sp_attr & SP_TRANSPARENT)) { + gDPSetRenderMode( gl++, + SPRITE_SURF, SPRITE_SURF2); + } + + if ((s->attr & SP_CUTOUT) && !(sp_attr & SP_CUTOUT)) { + gDPSetBlendColor ( gl++, 0xff, 0xff, 0xff, 0x01); + gDPSetAlphaCompare ( gl++, G_AC_THRESHOLD) ; + } else if (!(s->attr & SP_CUTOUT) && (sp_attr & SP_CUTOUT)) { + gDPSetAlphaCompare ( gl++, G_AC_NONE) ; + } + + if( (s->attr & SP_TEXSHIFT) && !(sp_attr & SP_TEXSHIFT) ) { + gDPSetTextureFilter( gl++, G_TF_AVERAGE ); + } else if( !(s->attr & SP_TEXSHIFT) && (sp_attr & SP_TEXSHIFT) ) { + gDPSetTextureFilter( gl++, G_TF_BILERP ); + }; + + }; + + sp_attr = s->attr; + + if( sp_attr & SP_Z ) { + gDPSetPrimDepth(gl++, s->zdepth, 0); + }; + + + gDPSetPrimColor( gl++, 0, 0, s->red, s->green, s->blue, s->alpha); + + if (s->bmfmt == G_IM_FMT_IA || s->bmfmt == G_IM_FMT_I) { + if( s->alpha == 255 ) { + gDPSetCombineMode ( gl++, + G_CC_MODULATEIDECALA_PRIM, + G_CC_MODULATEIDECALA_PRIM); + } else { + gDPSetCombineMode ( gl++, + G_CC_MODULATEIA_PRIM, + G_CC_MODULATEIA_PRIM); + }; + } else { + if( s->alpha == 255 ) { + gDPSetCombineMode ( gl++, + G_CC_MODULATEIDECALA_PRIM, + G_CC_MODULATEIDECALA_PRIM); + } else { + gDPSetCombineMode ( gl++, + G_CC_MODULATERGBA_PRIM, + G_CC_MODULATERGBA_PRIM); + }; + } + + + if( s->bmfmt == G_IM_FMT_CI ) { + gDPSetTextureLUT( gl++, G_TT_RGBA16); + gDPLoadTLUT( gl++, s->nTLUT, 256+s->startTLUT, s->LUT ); + gDPLoadSync( gl++ ); + }; + +#define MY_K0 (175 & 0x1ff) +#define MY_K1 (-43 & 0x1ff) +#define MY_K2 (-89 & 0x1ff) +#define MY_K3 (222 & 0x1ff) +#define MY_K4 (114 & 0x1ff) +#define MY_K5 (42 & 0x1ff) + + if( (s->bmfmt == G_IM_FMT_YUV) && (s->attr & SP_FASTCOPY) ) { + gDPSetTextureConvert( gl++, G_TC_CONV); + gDPSetTextureFilter( gl++, G_TF_POINT); + gDPSetCombineMode( gl++, G_CC_1CYUV2RGB, G_CC_1CYUV2RGB); + gDPSetConvert( gl++, MY_K0, MY_K1, MY_K2, MY_K3, MY_K4, MY_K5); + } else if(s->bmfmt == G_IM_FMT_YUV) { + gDPSetCycleType( gl++, G_CYC_2CYCLE ); + gDPSetTextureFilter( gl++, G_TF_BILERP); + gDPSetTextureConvert( gl++, G_TC_FILTCONV); + gDPSetConvert( gl++, MY_K0, MY_K1, MY_K2, MY_K3, MY_K4, MY_K5); + gDPSetCombineMode( gl++, G_CC_YUV2RGB, G_CC_PASS2); + } + + if (s->attr & SP_SCALE) { + sx = s->scalex; + sy = s->scaley; + } else { + sx = 1.0F; + sy = 1.0F; + } + + isx = (int) ((1<<10) / sx + 0.5F); + isy = (int) ((1<<10) / sy + 0.5F); + + if( b ) { + + if( (s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + gDPSetCycleType( gl++, G_CYC_COPY); + + x = 0.0F; + y = 0.0F; + + fty = s->y+y*sy; + ty = (int) ( fty + 0.99999F); + ft = (int) (isy * (ty - fty)); + ft = (ft + 16)>>5; + if( s->attr & SP_TEXSHIFT ) + ft += 16; /* 1/2 Texel for AntiAliasing */ + + if( s->attr & SP_FRACPOS ) + ft += s->frac_t; /* Micro-positioning */ + + y2 = y + s->bmheight; + ty2 = (int) (s->y+y2*sy + 0.99999F); + + if( (s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + ty2--; + + +#ifdef rmDEBUG + rmonPrintf("\tiscale=(%d,%d), %d bitmaps, sprite_size=(%d,%d)\n", + isx, isy, s->nbitmaps, s->width, s->height ); +#endif + + for( i=0; (i < s->nbitmaps) && (b->width > 0); i++, b++ ) { + + if( (x+b->width) > s->width ) { /* Next bitmap hits edge? */ + int bh; + + x = 0; + fs = 0; + ex = 0; + ey += s->expy; + y += s->bmheight; /* Wrap to next line */ + y2 = y + s->bmheight; /* Wrap to next line */ + + fty = s->y+y*sy; + ty = (int) ( fty + 0.9999F); + ft = (int) (isy * (ty - fty)); + ft = (ft + 16)>>5; + if( s->attr & SP_TEXSHIFT ) + ft += 16; /* 1/2 Texel for AntiAliasing */ + + if( s->attr & SP_FRACPOS ) + ft += s->frac_t; /* Micro-positioning */ + + ty2 = (int) (s->y+y2*sy + 0.9999F); + + ty += ey; + ty2 += ey; + + if( (s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + ty2--; + + /* Fill out to rect. bdy? */ + + if( (b->actualHeight != 0) ) + bh = b->actualHeight; + else + bh = s->bmheight; + + if( (y + bh) > s->height ) /* Can't wrap any more? */ + break; + }; + +#ifdef rmDEBUG + rmonPrintf("bm# %d, x,y=(%d,%d) width=%d \n", i, x, y, b->width ); +#endif + + ftx = s->x+x*sx; + tx = (s32) (ftx + 0.9999F); + fs = (s32) (isx * (tx - ftx)); + fs = (fs + 16)>>5; + if( s->attr & SP_TEXSHIFT ) + fs += 16; /* 1/2 Texel for AntiAliasing */ + + if( s->attr & SP_FRACPOS ) + fs += s->frac_s; /* Micro-positioning */ + + x2 = x + b->width; + tx2 = (int) (s->x+x2*sx + 0.9999F); + + if( (b->actualHeight != 0) ) { + y2 = y + b->actualHeight; + ty2 = (s32) (s->y+y2*sy + 0.9999F); + ty2 += ey; + + if( (s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + ty2--; + }; + +#ifdef rmDEBUG + rmonPrintf("\tfull(%g,%g) = int(%d,%d) + frac(%d,%d)\n", + ftx, fty, tx,ty, fs,ft ); +#endif + + tx += ex; + tx2 += ex; + + if( (s->attr & SP_FASTCOPY) && (s->bmfmt != G_IM_FMT_YUV) ) + tx2--; + + if( b->buf != NULL ) /* Skip over null bitmaps (blanks) */ + drawbitmap ( &gl, s, b, tx, ty, tx2, ty2, fs, ft, isx, isy); + + x += b->width; + ex += s->expx; + } + + if (s->attr & SP_FASTCOPY) + gDPSetCycleType( gl++, G_CYC_1CYCLE); + + if(s->bmfmt == G_IM_FMT_YUV) { + gDPSetCycleType( gl++, G_CYC_1CYCLE); + gDPSetTextureFilter ( gl++, G_TF_BILERP ); + gDPSetTextureConvert( gl++, G_TC_FILT ); + }; + + } else { + int rgba; + + x = (s32)s->x; + y = (s32)s->y; + x2 = s->x + (s->width*sx)-1; + y2 = s->y + (s->height*sy)-1; + + if( ( x >= scissor_xmax) || (y >= scissor_ymax) ) { +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: FILL Upper Left corner (%d,%d) beyond range (%d,%d)\n", + x, y, scissor_xmax, scissor_ymax ); +#endif + } else if( ( x2 < scissor_xmin) || (y2 < scissor_ymin) ) { +#ifdef DEBUG_SCISSOR + emPrintf("Sprite Scissoring: FILL Lower Right corner (%d,%d) below range (%d,%d)\n", + x2, y2, scissor_xmin, scissor_ymin ); +#endif + } else { + + if( x < scissor_xmin ) + x = scissor_xmin; + + if( x2 >= scissor_xmax ) + x2 = scissor_xmax - 1; + + if( y < scissor_ymin ) + y = scissor_ymin; + + if( y2 >= scissor_ymax ) + y2 = scissor_ymax - 1; + + rgba = GPACK_RGBA5551((s->red), (s->green), (s->blue), (s->alpha>>7)); + + gSPTexture ( gl++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_OFF); + gDPSetCycleType( gl++, G_CYC_FILL); + gDPSetFillColor( gl++, (rgba << 16) | (rgba) ); + + gDPFillRectangle( gl++, x,y, x2,y2 ); + gDPSetCycleType( gl++, G_CYC_1CYCLE); + gSPTexture ( gl++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON); + } + } + + if( s->bmfmt == G_IM_FMT_CI ) { + gDPSetTextureLUT( gl++, G_TT_NONE); + }; + + gSPEndDisplayList ( gl++ ); + + assert((gl - ogl) < s->ndisplist); + s->rsp_dl_next = gl; + return( dl_start ); +} + +void +spFinish( Gfx **glistp ) +{ + Gfx *gl; + + gl = *glistp; + + /* Turn off texturing */ + gSPTexture ( gl++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_OFF); + gDPSetCombineMode ( gl++, G_CC_SHADE, G_CC_SHADE); + + if (sp_attr & SP_TRANSPARENT) { + /* Turn off transparency */ + gDPSetRenderMode( gl++, G_RM_OPA_SURF, G_RM_OPA_SURF2); + } + + if (sp_attr & SP_CUTOUT) { + /* Turn off Alpha write enable */ + gDPSetAlphaCompare ( gl++, G_AC_NONE) ; + } + + gSPEndDisplayList ( gl++ ); + + *glistp = gl; +} diff --git a/lib/ultralib/src/sp/spriteex.c b/lib/ultralib/src/sp/spriteex.c new file mode 100644 index 0000000..772036f --- /dev/null +++ b/lib/ultralib/src/sp/spriteex.c @@ -0,0 +1,2 @@ +#define F3DEX_GBI +#include "sprite.c" diff --git a/lib/ultralib/src/sp/spriteex2.c b/lib/ultralib/src/sp/spriteex2.c new file mode 100644 index 0000000..2ef1221 --- /dev/null +++ b/lib/ultralib/src/sp/spriteex2.c @@ -0,0 +1,2 @@ +#define F3DEX_GBI_2 +#include "sprite.c" diff --git a/lib/ultralib/src/sp/spscale.c b/lib/ultralib/src/sp/spscale.c new file mode 100644 index 0000000..4f1bd92 --- /dev/null +++ b/lib/ultralib/src/sp/spscale.c @@ -0,0 +1,42 @@ +/* + * Copyright 1995, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * + * UNPUBLISHED -- Rights reserved under the copyright laws of the United + * States. Use of a copyright notice is precautionary only and does not + * imply publication or disclosure. + * + * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: + * Use, duplication or disclosure by the Government is subject to restrictions + * as set forth in FAR 52.227.19(c)(2) or subparagraph (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, or the DOD or NASA FAR + * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., + * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. + * + * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY + * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, + * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY + * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON + * GRAPHICS, INC. + */ + +#include <sp.h> + +/* + * spScale() + * + * Scales the sprite by a vertical and horizontal factor. + */ +void +spScale (Sprite *sp, float sx, float sy) +{ + + sp->scalex = sx; + sp->scaley = sy; + + if( (sx == 1.0F) && (sy == 1.0F) ) + spClearAttribute( sp, SP_SCALE ); + else + spSetAttribute( sp, SP_SCALE ); +} diff --git a/lib/ultralib/src/vimodes/vimodefpalhaf1.c b/lib/ultralib/src/vimodes/vimodefpalhaf1.c new file mode 100644 index 0000000..86e0f80 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHaf1 = { + OS_VI_FPAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpalhan1.c b/lib/ultralib/src/vimodes/vimodefpalhan1.c new file mode 100644 index 0000000..857c493 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHan1 = { + OS_VI_FPAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpalhpf1.c b/lib/ultralib/src/vimodes/vimodefpalhpf1.c new file mode 100644 index 0000000..366ed78 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHpf1 = { + OS_VI_FPAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpalhpf2.c b/lib/ultralib/src/vimodes/vimodefpalhpf2.c new file mode 100644 index 0000000..76eaa13 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHpf2 = { + OS_VI_FPAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpalhpn1.c b/lib/ultralib/src/vimodes/vimodefpalhpn1.c new file mode 100644 index 0000000..416e63e --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHpn1 = { + OS_VI_FPAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpalhpn2.c b/lib/ultralib/src/vimodes/vimodefpalhpn2.c new file mode 100644 index 0000000..3f3f165 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpalhpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalHpn2 = { + OS_VI_FPAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallaf1.c b/lib/ultralib/src/vimodes/vimodefpallaf1.c new file mode 100644 index 0000000..bc86c99 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLaf1 = { + OS_VI_FPAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallaf2.c b/lib/ultralib/src/vimodes/vimodefpallaf2.c new file mode 100644 index 0000000..8233460 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallaf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLaf2 = { + OS_VI_FPAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallan1.c b/lib/ultralib/src/vimodes/vimodefpallan1.c new file mode 100644 index 0000000..30532a0 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLan1 = { + OS_VI_FPAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallan2.c b/lib/ultralib/src/vimodes/vimodefpallan2.c new file mode 100644 index 0000000..76ddf13 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallan2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLan2 = { + OS_VI_FPAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallpf1.c b/lib/ultralib/src/vimodes/vimodefpallpf1.c new file mode 100644 index 0000000..d743345 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLpf1 = { + OS_VI_FPAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallpf2.c b/lib/ultralib/src/vimodes/vimodefpallpf2.c new file mode 100644 index 0000000..04b4c6c --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLpf2 = { + OS_VI_FPAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(45, 615), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(47, 617), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallpn1.c b/lib/ultralib/src/vimodes/vimodefpallpn1.c new file mode 100644 index 0000000..634d984 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLpn1 = { + OS_VI_FPAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodefpallpn2.c b/lib/ultralib/src/vimodes/vimodefpallpn2.c new file mode 100644 index 0000000..cc1627a --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodefpallpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeFpalLpn2 = { + OS_VI_FPAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(47, 617), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhaf1.c b/lib/ultralib/src/vimodes/vimodempalhaf1.c new file mode 100644 index 0000000..0c3d605 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHaf1 = { + OS_VI_MPAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { //[0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { //[1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhan1.c b/lib/ultralib/src/vimodes/vimodempalhan1.c new file mode 100644 index 0000000..0566ccc --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHan1 = { + OS_VI_MPAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhpf1.c b/lib/ultralib/src/vimodes/vimodempalhpf1.c new file mode 100644 index 0000000..3aa2b6b --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHpf1 = { + OS_VI_MPAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhpf2.c b/lib/ultralib/src/vimodes/vimodempalhpf2.c new file mode 100644 index 0000000..128ca15 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHpf2 = { + OS_VI_MPAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhpn1.c b/lib/ultralib/src/vimodes/vimodempalhpn1.c new file mode 100644 index 0000000..d589ad9 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHpn1 = { + OS_VI_MPAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempalhpn2.c b/lib/ultralib/src/vimodes/vimodempalhpn2.c new file mode 100644 index 0000000..57f43cd --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempalhpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalHpn2 = { + OS_VI_MPAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallaf1.c b/lib/ultralib/src/vimodes/vimodempallaf1.c new file mode 100644 index 0000000..2d726e7 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLaf1 = { + OS_VI_MPAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallaf2.c b/lib/ultralib/src/vimodes/vimodempallaf2.c new file mode 100644 index 0000000..8eac118 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallaf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLaf2 = { + OS_VI_MPAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallan1.c b/lib/ultralib/src/vimodes/vimodempallan1.c new file mode 100644 index 0000000..2a4f73a --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLan1 = { + OS_VI_MPAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallan2.c b/lib/ultralib/src/vimodes/vimodempallan2.c new file mode 100644 index 0000000..2ff5fad --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallan2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLan2 = { + OS_VI_MPAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallpf1.c b/lib/ultralib/src/vimodes/vimodempallpf1.c new file mode 100644 index 0000000..d89f113 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLpf1 = { + OS_VI_MPAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallpf2.c b/lib/ultralib/src/vimodes/vimodempallpf2.c new file mode 100644 index 0000000..2e5386b --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLpf2 = { + OS_VI_MPAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(524), // vSync + HSYNC(3088, 0), // hSync + LEAP(3100, 3100), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(2, 2, 11, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallpn1.c b/lib/ultralib/src/vimodes/vimodempallpn1.c new file mode 100644 index 0000000..420d5e6 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLpn1 = { + OS_VI_MPAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodempallpn2.c b/lib/ultralib/src/vimodes/vimodempallpn2.c new file mode 100644 index 0000000..8195790 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodempallpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeMpalLpn2 = { + OS_VI_MPAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 30, 5, 70), // burst + VSYNC(525), // vSync + HSYNC(3089, 4), // hSync + LEAP(3097, 3098), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschaf1.c b/lib/ultralib/src/vimodes/vimodentschaf1.c new file mode 100644 index 0000000..071b330 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHaf1 = { + OS_VI_NTSC_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschan1.c b/lib/ultralib/src/vimodes/vimodentschan1.c new file mode 100644 index 0000000..279bb83 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHan1 = { + OS_VI_NTSC_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschpf1.c b/lib/ultralib/src/vimodes/vimodentschpf1.c new file mode 100644 index 0000000..5ad8c2b --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHpf1 = { + OS_VI_NTSC_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschpf2.c b/lib/ultralib/src/vimodes/vimodentschpf2.c new file mode 100644 index 0000000..b9720a5 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHpf2 = { + OS_VI_NTSC_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschpn1.c b/lib/ultralib/src/vimodes/vimodentschpn1.c new file mode 100644 index 0000000..ae8c0a9 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHpn1 = { + OS_VI_NTSC_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentschpn2.c b/lib/ultralib/src/vimodes/vimodentschpn2.c new file mode 100644 index 0000000..5c73d69 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentschpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscHpn2 = { + OS_VI_NTSC_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclaf1.c b/lib/ultralib/src/vimodes/vimodentsclaf1.c new file mode 100644 index 0000000..31ff70b --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLaf1 = { + OS_VI_NTSC_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclaf2.c b/lib/ultralib/src/vimodes/vimodentsclaf2.c new file mode 100644 index 0000000..fd15f40 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclaf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLaf2 = { + OS_VI_NTSC_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclan1.c b/lib/ultralib/src/vimodes/vimodentsclan1.c new file mode 100644 index 0000000..9a052be --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLan1 = { + OS_VI_NTSC_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclan2.c b/lib/ultralib/src/vimodes/vimodentsclan2.c new file mode 100644 index 0000000..fa66af4 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclan2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLan2 = { + OS_VI_NTSC_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclpf1.c b/lib/ultralib/src/vimodes/vimodentsclpf1.c new file mode 100644 index 0000000..dd146b9 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLpf1 = { + OS_VI_NTSC_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclpf2.c b/lib/ultralib/src/vimodes/vimodentsclpf2.c new file mode 100644 index 0000000..6cda2a1 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLpf2 = { + OS_VI_NTSC_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(524), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(35, 509), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclpn1.c b/lib/ultralib/src/vimodes/vimodentsclpn1.c new file mode 100644 index 0000000..ff6172c --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLpn1 = { + OS_VI_NTSC_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodentsclpn2.c b/lib/ultralib/src/vimodes/vimodentsclpn2.c new file mode 100644 index 0000000..6340981 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodentsclpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModeNtscLpn2 = { + OS_VI_NTSC_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(57, 34, 5, 62), // burst + VSYNC(525), // vSync + HSYNC(3093, 0), // hSync + LEAP(3093, 3093), // leap + HSTART(108, 748), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(37, 511), // vStart + BURST(4, 2, 14, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhaf1.c b/lib/ultralib/src/vimodes/vimodepalhaf1.c new file mode 100644 index 0000000..791a918 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHaf1 = { + OS_VI_PAL_HAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhan1.c b/lib/ultralib/src/vimodes/vimodepalhan1.c new file mode 100644 index 0000000..947a0c1 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHan1 = { + OS_VI_PAL_HAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhpf1.c b/lib/ultralib/src/vimodes/vimodepalhpf1.c new file mode 100644 index 0000000..6c9e915 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHpf1 = { + OS_VI_PAL_HPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhpf2.c b/lib/ultralib/src/vimodes/vimodepalhpf2.c new file mode 100644 index 0000000..62d162e --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHpf2 = { + OS_VI_PAL_HPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(640), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(0.5, 0.5), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(0.5, 0.5), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhpn1.c b/lib/ultralib/src/vimodes/vimodepalhpn1.c new file mode 100644 index 0000000..a06efac --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHpn1 = { + OS_VI_PAL_HPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepalhpn2.c b/lib/ultralib/src/vimodes/vimodepalhpn2.c new file mode 100644 index 0000000..0ed9dfc --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepalhpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalHpn2 = { + OS_VI_PAL_HPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(1280), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(1, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(2560), // origin + SCALE(1, 0), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(5120), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallaf1.c b/lib/ultralib/src/vimodes/vimodepallaf1.c new file mode 100644 index 0000000..1a43489 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallaf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLaf1 = { + OS_VI_PAL_LAF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallaf2.c b/lib/ultralib/src/vimodes/vimodepallaf2.c new file mode 100644 index 0000000..89bd8a2 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallaf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLaf2 = { + OS_VI_PAL_LAF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_SERRATE_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallan1.c b/lib/ultralib/src/vimodes/vimodepallan1.c new file mode 100644 index 0000000..3dd00be --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallan1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLan1 = { + OS_VI_PAL_LAN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_ANTIALIAS_MODE_1 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallan2.c b/lib/ultralib/src/vimodes/vimodepallan2.c new file mode 100644 index 0000000..bc5a270 --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallan2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLan2 = { + OS_VI_PAL_LAN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_DIVOT_ON | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallpf1.c b/lib/ultralib/src/vimodes/vimodepallpf1.c new file mode 100644 index 0000000..50828ce --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallpf1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLpf1 = { + OS_VI_PAL_LPF1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallpf2.c b/lib/ultralib/src/vimodes/vimodepallpf2.c new file mode 100644 index 0000000..da2fead --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallpf2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLpf2 = { + OS_VI_PAL_LPF2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_SERRATE_ON | VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(624), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0.25), // yScale + HSTART(93, 567), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0.75), // yScale + HSTART(95, 569), // vStart + BURST(105, 2, 13, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallpn1.c b/lib/ultralib/src/vimodes/vimodepallpn1.c new file mode 100644 index 0000000..e27e74b --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallpn1.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLpn1 = { + OS_VI_PAL_LPN1, // type + { // comRegs + VI_CTRL_TYPE_16 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_2 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(640), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/vimodes/vimodepallpn2.c b/lib/ultralib/src/vimodes/vimodepallpn2.c new file mode 100644 index 0000000..76fa04d --- /dev/null +++ b/lib/ultralib/src/vimodes/vimodepallpn2.c @@ -0,0 +1,35 @@ +#include "PR/os.h" +#include "PR/rcp.h" +#include "../io/viint.h" + +OSViMode osViModePalLpn2 = { + OS_VI_PAL_LPN2, // type + { // comRegs + VI_CTRL_TYPE_32 | VI_CTRL_GAMMA_DITHER_ON | VI_CTRL_GAMMA_ON | + VI_CTRL_ANTIALIAS_MODE_3 | VI_CTRL_PIXEL_ADV_3, // ctrl + WIDTH(320), // width + BURST(58, 30, 4, 69), // burst + VSYNC(625), // vSync + HSYNC(3177, 23), // hSync + LEAP(3183, 3181), // leap + HSTART(128, 768), // hStart + SCALE(2, 0), // xScale + VCURRENT(0), // vCurrent + }, + { // fldRegs + { // [0] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + }, + { // [1] + ORIGIN(1280), // origin + SCALE(1, 0), // yScale + HSTART(95, 569), // vStart + BURST(107, 2, 9, 0), // vBurst + VINTR(2), // vIntr + } + } +}; diff --git a/lib/ultralib/src/voice/voicecheckresult.c b/lib/ultralib/src/voice/voicecheckresult.c new file mode 100644 index 0000000..6f615e1 --- /dev/null +++ b/lib/ultralib/src/voice/voicecheckresult.c @@ -0,0 +1,23 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 __osVoiceCheckResult(OSVoiceHandle* hd, u8* stat) { + s32 ret; + u8 buf[2]; + + if (ret = __osVoiceGetStatus(hd->__mq, hd->__channel, stat), ret == 0) { + if (*stat & 1) { + ret = CONT_ERR_VOICE_NO_RESPONSE; + } else if (ret = __osVoiceContRead2(hd->__mq, hd->__channel, 0, buf), ret == 0) { + hd->cmd_status = buf[0] & 7; + + if (buf[0] & 0x40) { + ret = CONT_ERR_VOICE_NO_RESPONSE; + } else { + ret = buf[1] << 8; + } + } + } + return ret; +}
\ No newline at end of file diff --git a/lib/ultralib/src/voice/voicecheckword.c b/lib/ultralib/src/voice/voicecheckword.c new file mode 100644 index 0000000..25c51fa --- /dev/null +++ b/lib/ultralib/src/voice/voicecheckword.c @@ -0,0 +1,116 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 osVoiceCheckWord(u8* word) { + s32 k; + s32 ret = 0; + u16 sjis; + u16 old = 0; + + for (k = 0; word[k] != 0; k += 2) { + sjis = (word[k] << 8) + word[k + 1]; + if (((sjis != 'ー') && (sjis < 'ぁ')) + || ((sjis > 'ん') && (sjis < 'ァ')) + || (sjis == 0x837F) || (sjis > 'ヶ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if ((k == 0) && ((sjis == 'ー') || (sjis == 'ん') || (sjis == 'っ') + || (sjis == 'ゎ') || (sjis == 'ン') || (sjis == 'ッ') + || (sjis == 'ヮ') || (sjis == 'ヵ') || (sjis == 'ヶ')) + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ぁ') || (sjis == 'ァ')) + && (old != 'ふ') && (old != 'フ') && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ぃ') || (sjis == 'ィ')) && (old != 'う') + && (old != 'て') && (old != 'で') && (old != 'ふ') + && (old != 'ウ') && (old != 'テ') && (old != 'デ') + && (old != 'フ') && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ぅ') || (sjis == 'ゥ')) + && (old != 'と') && (old != 'ど') + && (old != 'ふ') + && (old != 'ト') && (old != 'ド') + && (old != 'フ') && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ぇ') || (sjis == 'ェ')) + && (old != 'う') + && (old != 'し') && (old != 'じ') + && (old != 'ち') && (old != 'ぢ') + && (old != 'つ') && (old != 'ふ') && (old != 'ウ') + && (old != 'シ') && (old != 'ジ') + && (old != 'チ') && (old != 'ヂ') + && (old != 'ツ') && (old != 'フ') && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ぉ') || (sjis == 'ォ')) + && (old != 'う') && (old != 'ふ') && (old != 'ウ') && (old != 'フ') && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ゃ') || (sjis == 'ゅ') || (sjis == 'ょ') + || (sjis == 'ャ') || (sjis == 'ュ') || (sjis == 'ョ')) + && (old != 'き') && (old != 'し') && (old != 'ち') + && (old != 'に') && (old != 'ひ') && (old != 'み') + && (old != 'り') && (old != 'ぎ') && (old != 'じ') + && (old != 'ぢ') && (old != 'び') && (old != 'ぴ') + && (old != 'キ') && (old != 'シ') && (old != 'チ') + && (old != 'ニ') && (old != 'ヒ') && (old != 'ミ') + && (old != 'リ') && (old != 'ギ') && (old != 'ジ') + && (old != 'ヂ') && (old != 'ビ') && (old != 'ピ') + && (old != 'ヴ') + ) { + ret = CONT_ERR_VOICE_WORD; + } else if ((sjis == 'ー') + && ((old == 'ん') || (old == 'っ') + || (old == 'ン') || (old == 'ッ')) + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((sjis == 'ん') || (sjis == 'ン')) + && ((old == 'ん') || (old == 'ン')) + ) { + ret = CONT_ERR_VOICE_WORD; + } else if (((old == 'っ') || (old == 'ッ')) + && ((sjis == 'ー') + || (sjis == 'あ') || (sjis == 'い') || (sjis == 'う') || (sjis == 'え') || (sjis == 'お') + || (sjis == 'な') || (sjis == 'に') || (sjis == 'ぬ') || (sjis == 'ね') || (sjis == 'の') + || (sjis == 'ま') || (sjis == 'み') || (sjis == 'む') || (sjis == 'め') || (sjis == 'も') + || (sjis == 'や') || (sjis == 'ゆ') || (sjis == 'よ') + || (sjis == 'ら') || (sjis == 'り') || (sjis == 'る') || (sjis == 'れ') || (sjis == 'ろ') + || (sjis == 'わ') || (sjis == 'ゐ') || (sjis == 'ゑ') || (sjis == 'を') + || (sjis == 'ん') + || (sjis == 'ぁ') || (sjis == 'ぃ') || (sjis == 'ぅ') || (sjis == 'ぇ') || (sjis == 'ぉ') + || (sjis == 'ゃ') || (sjis == 'ゅ') || (sjis == 'ょ') + || (sjis == 'っ') || (sjis == 'ゎ') + + || (sjis == 'ア') || (sjis == 'イ') || (sjis == 'ウ') || (sjis == 'エ') || (sjis == 'オ') + || (sjis == 'ナ') || (sjis == 'ニ') || (sjis == 'ヌ') || (sjis == 'ネ') || (sjis == 'ノ') + || (sjis == 'マ') || (sjis == 'ミ') || (sjis == 'ム') || (sjis == 'メ') || (sjis == 'モ') + || (sjis == 'ヤ') || (sjis == 'ユ') || (sjis == 'ヨ') + || (sjis == 'ラ') || (sjis == 'リ') || (sjis == 'ル') || (sjis == 'レ') || (sjis == 'ロ') + || (sjis == 'ワ') || (sjis == 'ヰ') || (sjis == 'ヱ') || (sjis == 'ヲ') + || (sjis == 'ン') + || (sjis == 'ァ') || (sjis == 'ィ') || (sjis == 'ゥ') || (sjis == 'ェ') || (sjis == 'ォ') + || (sjis == 'ャ') || (sjis == 'ュ') || (sjis == 'ョ') + || (sjis == 'ッ') || (sjis == 'ヮ') + ) + ) { + ret = CONT_ERR_VOICE_WORD; + } + + if (ret != 0) { + return ret; + } + + old = sjis; + } + + if ((sjis == 'っ') || (sjis == 'ッ')) { + ret = CONT_ERR_VOICE_WORD; + } + + return ret; +} diff --git a/lib/ultralib/src/voice/voicecleardictionary.c b/lib/ultralib/src/voice/voicecleardictionary.c new file mode 100644 index 0000000..ef6388f --- /dev/null +++ b/lib/ultralib/src/voice/voicecleardictionary.c @@ -0,0 +1,28 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 osVoiceClearDictionary(OSVoiceHandle* hd, u8 words) { + s32 ret; + u8 stat; + u8 buf[4]; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + *(u32*)buf = 0x02000000; + buf[2] = words; + + ERRCK(__osVoiceContWrite4(hd->__mq, hd->__channel, 0, buf)); + + ret = __osVoiceCheckResult(hd, &stat); + if (ret & 0xFF00) { + ret = CONT_ERR_INVALID; + } + + return ret; +} + diff --git a/lib/ultralib/src/voice/voicecontread2.c b/lib/ultralib/src/voice/voicecontread2.c new file mode 100644 index 0000000..ae4b07b --- /dev/null +++ b/lib/ultralib/src/voice/voicecontread2.c @@ -0,0 +1,75 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" +#include "io/controller_voice.h" + +#define READ2FORMAT(p) ((__OSVoiceRead2Format*)(ptr)) + +s32 __osVoiceContRead2(OSMesgQueue* mq, int channel, u16 address, u8* buffer) { + s32 ret; + u8 status; + int i; + u8* ptr; + int retry; + + retry = 2; + + __osSiGetAccess(); + + do { + + ptr = (u8*)&__osPfsPifRam.ramarray; + + if ((__osContLastCmd != CONT_CMD_READ2_VOICE) || (__osPfsLastChannel != channel)) { + __osContLastCmd = CONT_CMD_READ2_VOICE; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = 0; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + READ2FORMAT(ptr)->dummy = CONT_CMD_NOP; + READ2FORMAT(ptr)->txsize = CONT_CMD_READ2_VOICE_TX; + READ2FORMAT(ptr)->rxsize = CONT_CMD_READ2_VOICE_RX; + READ2FORMAT(ptr)->cmd = CONT_CMD_READ2_VOICE; + READ2FORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSVoiceRead2Format)] = CONT_CMD_END; + } else { + ptr = (u8*)&__osPfsPifRam.ramarray + channel; + } + + READ2FORMAT(ptr)->addrh = address >> 3; + READ2FORMAT(ptr)->addrl = __osContAddressCrc(address) | (address << 5); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = CHNL_ERR(*READ2FORMAT(ptr)); + + if (ret == 0) { + if (__osVoiceContDataCrc(&READ2FORMAT(ptr)->data, ARRLEN(READ2FORMAT(ptr)->data)) != READ2FORMAT(ptr)->datacrc) { + ret = __osVoiceGetStatus(mq, channel, &status); + if (ret != 0) { + break; + } + + ret = CONT_ERR_CONTRFAIL; + } else { + bcopy(&READ2FORMAT(ptr)->data, buffer, ARRLEN(READ2FORMAT(ptr)->data)); + } + } else { + ret = CONT_ERR_NO_CONTROLLER; + } + + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voicecontread36.c b/lib/ultralib/src/voice/voicecontread36.c new file mode 100644 index 0000000..a3c80a4 --- /dev/null +++ b/lib/ultralib/src/voice/voicecontread36.c @@ -0,0 +1,73 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" +#include "io/controller_voice.h" + +#define READ36FORMAT(p) ((__OSVoiceRead36Format*)(ptr)) + +s32 __osVoiceContRead36(OSMesgQueue* mq, s32 channel, u16 address, u8* buffer) { + s32 ret; + u8 status; + s32 i; + u8* ptr; + s32 retry = 2; + + __osSiGetAccess(); + + do { + + ptr = (u8*)&__osPfsPifRam.ramarray; + + if ((__osContLastCmd != CONT_CMD_READ36_VOICE) || (__osPfsLastChannel != channel)) { + __osContLastCmd = CONT_CMD_READ36_VOICE; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = 0; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + READ36FORMAT(ptr)->dummy = CONT_CMD_NOP; + READ36FORMAT(ptr)->txsize = CONT_CMD_READ36_VOICE_TX; + READ36FORMAT(ptr)->rxsize = CONT_CMD_READ36_VOICE_RX; + READ36FORMAT(ptr)->cmd = CONT_CMD_READ36_VOICE; + READ36FORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSVoiceRead36Format)] = CONT_CMD_END; + } else { + ptr = (u8*)&__osPfsPifRam + channel; + } + + READ36FORMAT(ptr)->addrh = address >> 3; + READ36FORMAT(ptr)->addrl = __osContAddressCrc(address) | (address << 5); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = CHNL_ERR(*READ36FORMAT(ptr)); + + if (ret == 0) { + if (__osVoiceContDataCrc(&READ36FORMAT(ptr)->data, ARRLEN(READ36FORMAT(ptr)->data)) != READ36FORMAT(ptr)->datacrc) { + ret = __osVoiceGetStatus(mq, channel, &status); + if (ret != 0) { + break; + } + + ret = CONT_ERR_CONTRFAIL; + } else { + bcopy(&READ36FORMAT(ptr)->data, buffer, ARRLEN(READ36FORMAT(ptr)->data)); + } + } else { + ret = CONT_ERR_NO_CONTROLLER; + } + + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voicecontrolgain.c b/lib/ultralib/src/voice/voicecontrolgain.c new file mode 100644 index 0000000..ffb833c --- /dev/null +++ b/lib/ultralib/src/voice/voicecontrolgain.c @@ -0,0 +1,22 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 __osVoiceSetADConverter(OSMesgQueue*, int ch, u8 cmd); + +s32 osVoiceControlGain(OSVoiceHandle *hd, s32 analog, s32 digital) { + s32 ret; + u8 cmd = (u8) (analog == 0 ? 0x18 : 0x98); + static u8 digital_table[] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0}; + + ERRCK(__osVoiceSetADConverter(hd->__mq,hd->__channel, cmd)); + + if ((digital < ARRLEN(digital_table)) && (digital >= 0)) { + cmd = digital_table[digital] + 2; + } else { + return CONT_ERR_INVALID; + } + + ERRCK(__osVoiceSetADConverter(hd->__mq,hd->__channel, cmd)); + return ret; +} diff --git a/lib/ultralib/src/voice/voicecontwrite20.c b/lib/ultralib/src/voice/voicecontwrite20.c new file mode 100644 index 0000000..3842e3c --- /dev/null +++ b/lib/ultralib/src/voice/voicecontwrite20.c @@ -0,0 +1,77 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" +#include "io/controller_voice.h" + +#define WRITE20FORMAT(p) ((__OSVoiceWrite20Format*)(ptr)) + +s32 __osVoiceContWrite20(OSMesgQueue* mq, int channel, u16 address, u8* buffer) { + s32 ret; + u8 status; + int i; + u8* ptr; + int retry; + u8 crc; + + retry = 2; + + __osSiGetAccess(); + + do { + + ptr = (u8*)&__osPfsPifRam; + + if ((__osContLastCmd != CONT_CMD_WRITE20_VOICE) || (__osPfsLastChannel != channel)) { + __osContLastCmd = CONT_CMD_WRITE20_VOICE; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = 0; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + WRITE20FORMAT(ptr)->dummy = CONT_CMD_NOP; + WRITE20FORMAT(ptr)->txsize = CONT_CMD_WRITE20_VOICE_TX; + WRITE20FORMAT(ptr)->rxsize = CONT_CMD_WRITE20_VOICE_RX; + WRITE20FORMAT(ptr)->cmd = CONT_CMD_WRITE20_VOICE; + WRITE20FORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSVoiceWrite20Format)] = CONT_CMD_END; + } else { + ptr = (u8*)&__osPfsPifRam.ramarray + channel; + } + + WRITE20FORMAT(ptr)->addrh = address >> 3; + WRITE20FORMAT(ptr)->addrl = __osContAddressCrc(address) | (address << 5); + + bcopy(buffer, &WRITE20FORMAT(ptr)->data, 20); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + crc = __osVoiceContDataCrc(buffer, 20); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = (WRITE20FORMAT(ptr)->rxsize & 0xC0) >> 4; + + if (ret == 0) { + if (crc != WRITE20FORMAT(ptr)->datacrc) { + ret = __osVoiceGetStatus(mq, channel, &status); + if (ret != 0) { + break; + } + + ret = CONT_ERR_CONTRFAIL; + } + } else { + ret = CONT_ERR_NO_CONTROLLER; + } + + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voicecontwrite4.c b/lib/ultralib/src/voice/voicecontwrite4.c new file mode 100644 index 0000000..c2af86d --- /dev/null +++ b/lib/ultralib/src/voice/voicecontwrite4.c @@ -0,0 +1,75 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" +#include "io/controller_voice.h" + +#define WRITE4FORMAT(p) ((__OSVoiceWrite4Format*)(ptr)) + +s32 __osVoiceContWrite4(OSMesgQueue* mq, int channel, u16 address, u8 dst[4]) { + s32 ret; + u8 status; + int i; + u8* ptr; + s32 retry = 2; + u8 crc; + + __osSiGetAccess(); + + do { + + ptr = (u8*)&__osPfsPifRam; + + if ((__osContLastCmd != CONT_CMD_WRITE4_VOICE) || (__osPfsLastChannel != channel)) { + __osContLastCmd = CONT_CMD_WRITE4_VOICE; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = 0; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + WRITE4FORMAT(ptr)->dummy = CONT_CMD_NOP; + WRITE4FORMAT(ptr)->txsize = CONT_CMD_WRITE4_VOICE_TX; + WRITE4FORMAT(ptr)->rxsize = CONT_CMD_WRITE4_VOICE_RX; + WRITE4FORMAT(ptr)->cmd = CONT_CMD_WRITE4_VOICE; + WRITE4FORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSVoiceWrite4Format)] = CONT_CMD_END; + } else { + ptr = (u8*)&__osPfsPifRam + channel; + } + + WRITE4FORMAT(ptr)->addrh = address >> 3; + WRITE4FORMAT(ptr)->addrl = __osContAddressCrc(address) | (address << 5); + + bcopy(dst, &WRITE4FORMAT(ptr)->data, 4); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + crc = __osVoiceContDataCrc(dst, 4); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = (WRITE4FORMAT(ptr)->rxsize & 0xC0) >> 4; + + if (ret == 0) { + if (crc != WRITE4FORMAT(ptr)->datacrc) { + ret = __osVoiceGetStatus(mq, channel, &status); + if (ret != 0) { + break; + } + + ret = CONT_ERR_CONTRFAIL; + } + } else { + ret = CONT_ERR_NO_CONTROLLER; + } + + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voicecountsyllables.c b/lib/ultralib/src/voice/voicecountsyllables.c new file mode 100644 index 0000000..89b4c63 --- /dev/null +++ b/lib/ultralib/src/voice/voicecountsyllables.c @@ -0,0 +1,59 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +// The VRU can store only 880 semisyllables of words in its dictionary. +// Use this function to determine the semisyllable count before adding a word with osVoiceSetWord, +// to properly see whether it will fit. + +void osVoiceCountSyllables(u8 *data, u32 *syllable) { + s32 k; + u16 sjis; + u16 old; + + old = 0; + *syllable = 1; + for (k = 0; data[k] != 0; k += 2) { + sjis = data[k + 1] + (data[k] << 8); + if ((sjis == 'あ') || (sjis == 'い') || (sjis == 'う') || (sjis == 'え') || (sjis == 'お') + || (sjis == 'ア') || (sjis == 'イ') || (sjis == 'ウ') || (sjis == 'エ') || (sjis == 'オ') + ) { + if (k == 0) { + *syllable += 2; + } else { + *syllable += 1; + } + } else if ((sjis == 'か') || (sjis == 'き') || (sjis == 'く') || (sjis == 'け') || (sjis == 'こ') + || (sjis == 'た') || (sjis == 'ち') || (sjis == 'つ') || (sjis == 'て') || (sjis == 'と') + || (sjis == 'ぱ') || (sjis == 'ぴ') || (sjis == 'ぷ') || (sjis == 'ぺ') || (sjis == 'ぽ') + || (sjis == 'カ') || (sjis == 'キ') || (sjis == 'ク') || (sjis == 'ケ') || (sjis == 'コ') + || (sjis == 'タ') || (sjis == 'チ') || (sjis == 'ツ') || (sjis == 'テ') || (sjis == 'ト') + || (sjis == 'パ') || (sjis == 'ピ') || (sjis == 'プ') || (sjis == 'ペ') || (sjis == 'ポ') + ) { + if (k == 0) { + *syllable += 2; + } else if ((old == 'っ') || (old == 'ッ')) { + *syllable += 2; + } else { + *syllable += 3; + } + } else if ((sjis == 'ぁ') || (sjis == 'ぃ') || (sjis == 'ぅ') || (sjis == 'ぇ') || (sjis == 'ぉ') + || (sjis == 'ゃ') || (sjis == 'ゅ') || (sjis == 'ょ') || (sjis == 'ゎ') + + || (sjis == 'ァ') || (sjis == 'ィ') || (sjis == 'ゥ') || (sjis == 'ェ') || (sjis == 'ォ') + || (sjis == 'ャ') || (sjis == 'ュ') || (sjis == 'ョ') || (sjis == 'ヮ') + || (sjis == 'ヵ') || (sjis == 'ヶ') + ) { + if ((old == 'あ') || (old == 'い') || (old == 'う') || (old == 'え') || (old == 'お') + || (old == 'ア') || (old == 'イ') || (old == 'ウ') || (old == 'エ') || (old == 'オ') + ) { + *syllable += 1; + } + } else if ((sjis == 'ん') || (sjis == 'ー') || (sjis == 'っ') || (sjis == 'ン') || (sjis == 'ッ')) { + *syllable += 1; + } else { + *syllable += 2; + } + old = sjis; + } +} diff --git a/lib/ultralib/src/voice/voicecrc.c b/lib/ultralib/src/voice/voicecrc.c new file mode 100644 index 0000000..95741e6 --- /dev/null +++ b/lib/ultralib/src/voice/voicecrc.c @@ -0,0 +1,40 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +#define VOICE_CRC_LENGTH 8 +#define VOICE_CRC_GENERATOR 0x85 + +u8 __osVoiceContDataCrc(u8* data, u32 length) { + s32 ret = 0; + u32 i; + u32 j; + + for (j = length; j != 0; j--, data++) { + // Loop over each i in the j starting with most significant + for (i = (1 << (VOICE_CRC_LENGTH - 1)); i != 0; i >>= 1) { + ret <<= 1; + if (*data & i) { + if (ret & (1 << VOICE_CRC_LENGTH)) { + // Same as ret++; ret ^= 0x85 since last i always 0 after the shift + ret ^= VOICE_CRC_GENERATOR - 1; + } else { + ret++; + } + } else if (ret & (1 << VOICE_CRC_LENGTH)) { + ret ^= VOICE_CRC_GENERATOR; + } + } + } + // Act like a j of zeros is appended to data + do { + ret <<= 1; + if (ret & (1 << VOICE_CRC_LENGTH)) { + ret ^= VOICE_CRC_GENERATOR; + } + j++; + } while (j < VOICE_CRC_LENGTH); + + // Discarding the excess is done automatically by the return type + return ret; +}
\ No newline at end of file diff --git a/lib/ultralib/src/voice/voicegetreaddata.c b/lib/ultralib/src/voice/voicegetreaddata.c new file mode 100644 index 0000000..5627846 --- /dev/null +++ b/lib/ultralib/src/voice/voicegetreaddata.c @@ -0,0 +1,94 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" + +s32 osVoiceGetReadData(OSVoiceHandle* hd, OSVoiceData* micdata) { + s32 ret = 0; + s32 i; + u8 stat; + u8 temp[36]; + static u8 c; + + switch (hd->__mode) { + case 1: + ret = __osVoiceGetStatus(hd->__mq, hd->__channel, &stat); + if (ret != 0) { + return ret; + } else if (stat & 1) { + return CONT_ERR_NOT_READY; + } + + ERRCK(__osVoiceContRead2(hd->__mq, hd->__channel, 0, temp)); + + c = temp[0] & 7; + hd->cmd_status = c; + if ((c != 0) && (c != 7)) { + return CONT_ERR_NOT_READY; + } + case 2: + hd->__mode = 2; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)) + + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + *(u32*)temp = 0x600; + ERRCK(__osVoiceContWrite4(hd->__mq, hd->__channel, 0, temp)); + + case 3: + hd->__mode = 3; + + ret = __osVoiceGetStatus(hd->__mq, hd->__channel, &stat); + if (ret != 0) { + return ret; + } else if (stat & 1) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + ERRCK(__osVoiceContRead36(hd->__mq, hd->__channel, 0, temp)); + + micdata->warning = temp[4] + (temp[5] << 8); + micdata->answer_num = temp[6]; + micdata->voice_level = temp[8] + (temp[9] << 8); + micdata->voice_sn = temp[10] + (temp[11] << 8); + micdata->voice_time = temp[12] + (temp[13] << 8); + + for (i = 0; i < 5; i++) { + micdata->answer[i] = temp[14 + (i << 2)] + (temp[15 + (i << 2)] << 8); + micdata->distance[i] = temp[16 + (i << 2)] + (temp[17 + (i << 2)] << 8); + } + + if (micdata->answer[0] == 0x7FFF) { + micdata->answer_num = 0; + } + + hd->cmd_status = temp[34] & 7; + if ((c == 0) || (hd->cmd_status == 0)) { + break; + } + case 4: + hd->__mode = 4; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + + if (stat & 1) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + ERRCK(__osVoiceContRead2(hd->__mq, hd->__channel, 0, temp)); + + hd->cmd_status = temp[0] & 7; + if (temp[0] & 7) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + break; + default: + return CONT_ERR_INVALID; + } + hd->__mode = 0; + return ret; +} diff --git a/lib/ultralib/src/voice/voicegetstatus.c b/lib/ultralib/src/voice/voicegetstatus.c new file mode 100644 index 0000000..8d33f31 --- /dev/null +++ b/lib/ultralib/src/voice/voicegetstatus.c @@ -0,0 +1,61 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" + +s32 __osVoiceGetStatus(OSMesgQueue* mq, s32 port, u8* status) { + __OSContRequesFormatShort header; + s32 ret = 0; + s32 i; + u8* ptr = (u8*)&__osContPifRam.ramarray; + s32 retry = 2; + + __osSiGetAccess(); + + do { + if (ret != CONT_ERR_CONTRFAIL) { + __osContPifRam.pifstatus = CONT_CMD_EXE; + + for (i = 0; i < port; i++, *ptr++ = 0) { + ; + } + + *ptr++ = CONT_CMD_REQUEST_STATUS_TX; + *ptr++ = CONT_CMD_REQUEST_STATUS_RX; + *ptr = CONT_CMD_REQUEST_STATUS; + ptr += 4; + *ptr = CONT_CMD_END; + + __osContLastCmd = CONT_CMD_END; + ret = __osSiRawStartDma(OS_WRITE, &__osContPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + } + ret = __osSiRawStartDma(OS_READ, &__osContPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ptr = (u8*)&__osContPifRam.ramarray + port; + + header = *((__OSContRequesFormatShort*)ptr); + + ret = CHNL_ERR(header); + *status = header.status; + + if (ret == 0) { + if (header.typeh == 0 && header.typel == 1) { + if (header.status & 4) { + ret = CONT_ERR_CONTRFAIL; + } + } else { + ret = CONT_ERR_DEVICE; + } + } else if (ret & CONT_NO_RESPONSE_ERROR) { + ret = CONT_ERR_NO_CONTROLLER; + } else { + ret = CONT_ERR_CONTRFAIL; + } + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voiceinit.c b/lib/ultralib/src/voice/voiceinit.c new file mode 100644 index 0000000..a60f943 --- /dev/null +++ b/lib/ultralib/src/voice/voiceinit.c @@ -0,0 +1,40 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 osVoiceInit(OSMesgQueue* mq, OSVoiceHandle* handle, int channel) { + s32 ret; + s32 i; + u8 stat = 0; + u8 buf[4]; + static u8 cmd[] = {0x1E, 0x6E, 0x08, 0x56, 0x03}; + + handle->__channel = channel; + handle->__mq = mq; + handle->__mode = 0; + + ERRCK(__osVoiceGetStatus(mq, channel, &stat)); + + if (__osContChannelReset(mq, channel) != 0) { + return CONT_ERR_CONTRFAIL; + } + + for (i = 0; i < ARRLEN(cmd); i++) { + ERRCK(__osVoiceSetADConverter(mq, channel, cmd[i])); + } + + ERRCK(__osVoiceGetStatus(mq, channel, &stat)); + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + *(u32*)buf = 0x100; + ERRCK(__osVoiceContWrite4(mq, channel, 0, buf)); + + ret = __osVoiceCheckResult(handle, &stat); + if (ret & 0xFF00) { + ret = CONT_ERR_INVALID; + } + + return ret; +} diff --git a/lib/ultralib/src/voice/voiceinternal.h b/lib/ultralib/src/voice/voiceinternal.h new file mode 100644 index 0000000..899c150 --- /dev/null +++ b/lib/ultralib/src/voice/voiceinternal.h @@ -0,0 +1,10 @@ +#ifndef VOICE_INTERNAL_H +#define VOICE_INTERNAL_H + +// Various prototypes and externs that don't show up in os_voice.h +extern s32 __osPfsLastChannel; + +u8 __osVoiceContDataCrc(u8* data, u32 length); +s32 __osVoiceCheckResult(OSVoiceHandle* hd, u8* stat); + +#endif diff --git a/lib/ultralib/src/voice/voicemaskdictionary.c b/lib/ultralib/src/voice/voicemaskdictionary.c new file mode 100644 index 0000000..a017e3d --- /dev/null +++ b/lib/ultralib/src/voice/voicemaskdictionary.c @@ -0,0 +1,47 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" + +s32 osVoiceMaskDictionary(OSVoiceHandle* hd, u8* pattern, int size) { + s32 ret; + s32 i; + s32 j; + u8 stat; + u8 buf[20]; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + if (size & 1) { + j = size + 1; + } else { + j = size; + } + + bzero(&buf, ARRLEN(buf)); + + buf[18 - j] = 4; + + for (i = 0; i < j; i += 2) { + buf[i + ARRLEN(buf) - j] = pattern[i]; + buf[i + ARRLEN(buf) - j + 1] = pattern[i + 1]; + } + + if (size & 1) { + buf[ARRLEN(buf) - 1] = 0; + } + + ret = __osVoiceContWrite20(hd->__mq, hd->__channel, 0, &buf); + if (ret == 0) { + ret = __osVoiceCheckResult(hd, &stat); + if (ret & 0xFF00) { + ret = CONT_ERR_INVALID; + } + } + + return ret; +} diff --git a/lib/ultralib/src/voice/voicesetadconverter.c b/lib/ultralib/src/voice/voicesetadconverter.c new file mode 100644 index 0000000..2287c0d --- /dev/null +++ b/lib/ultralib/src/voice/voicesetadconverter.c @@ -0,0 +1,70 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" +#include "io/controller_voice.h" + +#define SWRITEFORMAT(p) ((__OSVoiceSWriteFormat*)(p)) + +s32 __osVoiceSetADConverter(OSMesgQueue* mq, s32 channel, u8 data) { + s32 ret; + int i; + u8* ptr; + u8 status; + int retry = 2; + + __osSiGetAccess(); + + do { + + ptr = (u8*)__osPfsPifRam.ramarray; + + if ((__osContLastCmd != CONT_CMD_SWRITE_VOICE) || (__osPfsLastChannel != channel)) { + __osContLastCmd = CONT_CMD_SWRITE_VOICE; + __osPfsLastChannel = channel; + + for (i = 0; i < channel; i++) { + *ptr++ = 0; + } + + __osPfsPifRam.pifstatus = CONT_CMD_EXE; + + SWRITEFORMAT(ptr)->txsize = CONT_CMD_SWRITE_VOICE_TX; + SWRITEFORMAT(ptr)->rxsize = CONT_CMD_SWRITE_VOICE_RX; + SWRITEFORMAT(ptr)->cmd = CONT_CMD_SWRITE_VOICE; + SWRITEFORMAT(ptr)->datacrc = 0; + + ptr[sizeof(__OSVoiceSWriteFormat)] = CONT_CMD_END; + } else { + ptr = (u8*)&__osPfsPifRam + channel; + } + + SWRITEFORMAT(ptr)->data = data; + SWRITEFORMAT(ptr)->scrc = __osContAddressCrc(data * 8); + + __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = CHNL_ERR(*SWRITEFORMAT(ptr)); + + if (ret == 0) { + if (SWRITEFORMAT(ptr)->datacrc & 1) { + ret = __osVoiceGetStatus(mq, channel, &status); + if (ret != 0) { + break; + } + + ret = CONT_ERR_CONTRFAIL; + } + } else { + ret = CONT_ERR_NO_CONTROLLER; + } + + } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0)); + + __osSiRelAccess(); + + return ret; +} diff --git a/lib/ultralib/src/voice/voicesetword.c b/lib/ultralib/src/voice/voicesetword.c new file mode 100644 index 0000000..9a7ed6f --- /dev/null +++ b/lib/ultralib/src/voice/voicesetword.c @@ -0,0 +1,44 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" + +s32 osVoiceSetWord(OSVoiceHandle *hd, u8 *word) { + s32 j; + s32 k; + s32 ret; + u8 stat; + u8 buf[40]; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + for (k = 0; word[k] != 0; k += 2) { + ; + } + + bzero(buf, ARRLEN(buf)); + + for (j = 0; j < k; j += 2) { + buf[ARRLEN(buf) - 1 - k + j] = word[j]; + buf[ARRLEN(buf) - 1 - k + j - 1] = word[j + 1]; + } + + buf[ARRLEN(buf) - 1 - j - 5] = 3; + + if (k >= 15) { + ERRCK(__osVoiceContWrite20(hd->__mq, hd->__channel, 0, buf)); + } + ERRCK(__osVoiceContWrite20(hd->__mq, hd->__channel, 0, buf + 20)); + ret = __osVoiceCheckResult(hd, &stat); + if (ret != 0) { + if (ret & 0x100) { + ret = CONT_ERR_VOICE_MEMORY; + } else if (ret & 0x200) { + ret = CONT_ERR_VOICE_WORD; + } else if (ret & 0xFF00) { + ret = CONT_ERR_INVALID; + } + } + return ret; +} diff --git a/lib/ultralib/src/voice/voicestartreaddata.c b/lib/ultralib/src/voice/voicestartreaddata.c new file mode 100644 index 0000000..0f9fc73 --- /dev/null +++ b/lib/ultralib/src/voice/voicestartreaddata.c @@ -0,0 +1,35 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" + +s32 osVoiceStartReadData(OSVoiceHandle* hd) { + s32 ret; + u8 stat; + u8 temp[4]; + + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + if (hd->__mode != 0) { + return CONT_ERR_INVALID; + } + + *(u32*)temp = 0x5000000; + ret = __osVoiceContWrite4(hd->__mq, hd->__channel, 0, temp); + + if (ret == 0) { + ret = __osVoiceCheckResult(hd, &stat); + + if (ret & 0xFF00) { + ret = CONT_ERR_INVALID; + } else { + hd->__mode = 1; + } + } + + return ret; +}
\ No newline at end of file diff --git a/lib/ultralib/src/voice/voicestopreaddata.c b/lib/ultralib/src/voice/voicestopreaddata.c new file mode 100644 index 0000000..e5b97ca --- /dev/null +++ b/lib/ultralib/src/voice/voicestopreaddata.c @@ -0,0 +1,44 @@ +#include "PR/os_internal.h" +#include "io/controller.h" +#include "PR/os_voice.h" +#include "voiceinternal.h" + +s32 osVoiceStopReadData(OSVoiceHandle* hd) { + s32 ret; + s32 i; + u8 stat; + u8 temp[4]; + + ERRCK(__osVoiceGetStatus(hd->__mq, hd->__channel, &stat)); + + if (stat & 2) { + return CONT_ERR_VOICE_NO_RESPONSE; + } + + if (hd->__mode == 0) { + return CONT_ERR_INVALID; + } + + *(u32*)temp = 0x700; + ret = __osVoiceContWrite4(hd->__mq, hd->__channel, 0, temp); + + if (ret == 0) { + i = 0; + do { + ret = __osVoiceCheckResult(hd, &stat); + if (ret & 0xFF00) { + if (((ret & 7) == 0) || ((ret & 7) == 7)) { + ret = 0; + hd->__mode = 0; + } else { + ret = CONT_ERR_INVALID; + } + } else { + hd->__mode = 0; + } + i++; + } while ((ret == CONT_ERR_VOICE_NO_RESPONSE) && (i < 20)); + } + + return ret; +}
\ No newline at end of file |
