diff --git a/Makefile b/Makefile index 8795584..546326e 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,11 @@ build/src/libultra/os/gettime.c.o: OPTFLAGS := -O1 build/src/libultra/os/timerintr.c.o: OPTFLAGS := -O1 build/src/libultra/os/setglobalintmask.c.o: OPTFLAGS := -O1 build/src/libultra/os/resetglobalintmask.c.o: OPTFLAGS := -O1 +build/src/libultra/os/settime.c.o: OPTFLAGS := -O1 +build/src/libultra/os/yieldthread.c.o: OPTFLAGS := -O1 +build/src/libultra/os/settimer.c.o: OPTFLAGS := -O1 +build/src/libultra/os/startthread.c.o: OPTFLAGS := -O1 +build/src/libultra/os/sethwinterrupt.c.o: OPTFLAGS := -O1 build/src/libultra/io/pigetcmdq.c.o: OPTFLAGS := -O1 build/src/libultra/io/sptask.c.o: OPTFLAGS := -O1 build/src/libultra/io/controller.c.o: OPTFLAGS := -O1 @@ -87,12 +92,20 @@ build/src/libultra/io/sp.c.o: OPTFLAGS := -O1 build/src/libultra/io/viswapbuf.c.o: OPTFLAGS := -O1 build/src/libultra/io/sptaskyielded.c.o: OPTFLAGS := -O1 build/src/libultra/io/vi.c.o: OPTFLAGS := -O1 +build/src/libultra/io/visetevent.c.o: OPTFLAGS := -O1 +build/src/libultra/io/aisetnextbuf.c.o: OPTFLAGS := -O1 +build/src/libultra/io/ai.c.o: OPTFLAGS := -O1 +build/src/libultra/io/vigetcurrframebuf.c.o: OPTFLAGS := -O1 +build/src/libultra/io/spsetpc.c.o: OPTFLAGS := -O1 build/src/libultra/libc/ll.c.o: OPTFLAGS := -O1 build/src/libultra/libc/ll.c.o: MIPS_VERSION := -mips3 -32 +build/src/libultra/libc/llcvt.c.o: OPTFLAGS := -O1 +build/src/libultra/libc/llcvt.c.o: MIPS_VERSION := -mips3 -32 # cheap hack. TODO: Make the override better build/src/libultra/io/gbpakpower.c.o: OPTFLAGS += -Wo,-loopunroll,0 build/src/libultra/io/gbpakinit.c.o: OPTFLAGS += -Wo,-loopunroll,0 +build/src/libultra/io/gbpakselectbank.c.o: OPTFLAGS += -Wo,-loopunroll,0 # Libultra misc build/src/libultra/gu/scale.c.o: CC := $(CC_OLD) @@ -114,6 +127,10 @@ build/src/libultra/gu/cosf.c.o: CC := $(CC_OLD) build/src/libultra/gu/random.c.o: CC := $(CC_OLD) build/src/libultra/libc/xprintf.c.o: CC := $(CC_OLD) build/src/libultra/libc/xprintf.c.o: OPTFLAGS := -O3 +build/src/libultra/libc/xldtob.c.o: CC := $(CC_OLD) +build/src/libultra/libc/xldtob.c.o: OPTFLAGS := -O3 +build/src/libultra/libc/xlitob.c.o: CC := $(CC_OLD) +build/src/libultra/libc/xlitob.c.o: OPTFLAGS := -O3 build/src/libultra/libc/string.c.o: CC := $(CC_OLD) build/src/libultra/libc/string.c.o: OPTFLAGS := -O3 build/src/libultra/io/controller.c.o: CC := $(CC_OLD) @@ -137,15 +154,31 @@ build/src/libultra/al/env.c.o: CC := $(CC_OLD) build/src/libultra/al/resample.c.o: CC := $(CC_OLD) build/src/libultra/al/resample.c.o: OPTFLAGS := -O3 build/src/libultra/al/save.c.o: CC := $(CC_OLD) +build/src/libultra/al/heapalloc.c.o: CC := $(CC_OLD) build/src/libultra/gu/mtxutil.c.o: CC := $(CC_OLD) build/src/libultra/gu/mtxutil.c.o: OPTFLAGS := -O3 build/src/libultra/io/pfsisplug.c.o: CC := $(CC_OLD) build/src/libultra/io/conteepprobe.c.o: CC := $(CC_OLD) build/src/libultra/io/conteepwrite.c.o: CC := $(CC_OLD) +build/src/libultra/io/conteepread.c.o: CC := $(CC_OLD) build/src/libultra/io/contpfs.c.o: CC := $(CC_OLD) build/src/libultra/io/viswapcontext.c.o: CC := $(CC_OLD) +build/src/libultra/io/contramwrite.c.o: CC := $(CC_OLD) +build/src/libultra/io/contramread.c.o: CC := $(CC_OLD) +build/src/libultra/io/crc.c.o: CC := $(CC_OLD) +build/src/libultra/libc/ldiv.c.o: CC := $(CC_OLD) +build/src/libultra/io/vimgr.c.o: CC := $(CC_OLD) +build/src/libultra/io/visetxscale.c.o: CC := $(CC_OLD) +build/src/libultra/io/visetxscale.c.o: OPTFLAGS := -O1 +build/src/libultra/io/visetyscale.c.o: CC := $(CC_OLD) +build/src/libultra/io/visetyscale.c.o: OPTFLAGS := -O1 +build/src/libultra/al/synallocfx.c.o: CC := $(CC_OLD) +build/src/libultra/al/synallocfx.c.o: OPTFLAGS := -O3 build/src/libultra/io/gbpakcheckconnector.c.o: CC := $(CC_OLD) +build/src/libultra/io/gbpakreadid.c.o: CC := $(CC_OLD) +build/src/libultra/io/gbpakreadwrite.c.o: CC := $(CC_OLD) +build/src/libultra/io/gbpakselectbank.c.o: CC := $(CC_OLD) ######################## Flags ############################# @@ -197,6 +230,11 @@ $(BUILD_DIR)/src/libultra/libc/ll.c.o: src/libultra/libc/ll.c python3 tools/set_o32abi_bit.py $@ @$(OBJDUMP) $(OBJDUMP_FLAGS) $@ > $(@:.o=.s) +$(BUILD_DIR)/src/libultra/libc/llcvt.c.o: src/libultra/libc/llcvt.c + $(CC) -c $(CFLAGS) $(OPTFLAGS) -o $@ $^ + python3 tools/set_o32abi_bit.py $@ + @$(OBJDUMP) $(OBJDUMP_FLAGS) $@ > $(@:.o=.s) + $(BUILD_DIR)/%.s.o: %.s $(AS) $(ASFLAGS) -o $@ $< diff --git a/include/PR/xstdio.h b/include/PR/xstdio.h index 6a6e81d..b993644 100644 --- a/include/PR/xstdio.h +++ b/include/PR/xstdio.h @@ -24,6 +24,26 @@ typedef struct /* 34 */ char length; } printf_struct; +// these are the same struct. TODO: Merge +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 @@ -32,7 +52,7 @@ typedef struct typedef char *outfun(char*,const char*,size_t); int _Printf(outfun prout, char *arg, const char *fmt, va_list args); -void _Litob(printf_struct *args, char type); -void _Ldtob(printf_struct *args, char type); +void _Litob(_Pft *args, char type); +void _Ldtob(_Pft *args, char type); #endif diff --git a/include/audio/synthInternals.h b/include/audio/synthInternals.h index 9a1e970..07c08bc 100644 --- a/include/audio/synthInternals.h +++ b/include/audio/synthInternals.h @@ -332,4 +332,7 @@ 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/splat.yaml b/splat.yaml index 49d915d..83a5632 100644 --- a/splat.yaml +++ b/splat.yaml @@ -272,47 +272,48 @@ segments: - [0x63B60, c, libultra/io/pigetcmdq] - [0x63B90, c, libultra/gu/cosf] - [0x63D00, c, libultra/io/epiread] - - [0x63D50, asm, libultra/io/visetspecial] - - [0x63EB0, asm, libultra/os/settime] - - [0x63EE0, asm, libultra/io/visetevent] - - [0x63F50, asm, libultra/io/gbpakreadid] - - [0x64110, asm, libultra/io/cartrominit] - - [0x64270, asm, libultra/io/pfsselectbank] - - [0x642F0, asm, libultra/os/setfpccsr] - - [0x64300, asm, libultra/io/aigetlen] - - [0x64310, asm, libultra/io/epiwrite] - - [0x64360, asm, libultra/os/maptlbrdb] - - [0x643C0, asm, libultra/os/yieldthread] - - [0x64410, asm, libultra/io/contramwrite] - - [0x64660, asm, libultra/io/contramread] - - [0x64890, asm, libultra/io/crc] + - [0x63D50, c, libultra/io/visetspecial] + - [0x63EB0, c, libultra/os/settime] + - [0x63EE0, c, libultra/io/visetevent] + - [0x63F50, c, libultra/io/gbpakreadid] + - [0x64110, c, libultra/io/cartrominit] + - [0x64270, c, libultra/io/pfsselectbank] + - [0x642F0, hasm, libultra/os/setfpccsr] + - [0x64300, c, libultra/io/aigetlen] + - [0x64310, c, libultra/io/epiwrite] + - [0x64360, hasm, libultra/os/maptlbrdb] + - [0x643C0, c, libultra/os/yieldthread] + - [0x64410, c, libultra/io/contramwrite] + - [0x64660, c, libultra/io/contramread] + - [0x64890, c, libultra/io/crc] - [0x64A00, hasm, libultra/os/__osGetCause] - - [0x64A10, asm, libultra/io/epirawwrite] - - [0x64B70, asm, libultra/os/settimer] - - [0x64C50, asm, libultra/libc/xldtob] - - [0x65710, asm, libultra/libc/ldiv] - - [0x658A0, asm, libultra/libc/xlitob] - - [0x65B40, asm, libultra/io/sirawwrite] - - [0x65B90, asm, libultra/io/spsetstat] - - [0x65BA0, asm, libultra/io/spgetstat] - - [0x65BC0, asm, libultra/io/vimgr] - - [0x65ED0, asm, libultra/io/vigetcurrcontext] - - [0x65EE0, asm, libultra/os/writebackdcacheall] - - [0x65F10, asm, libultra/al/heapalloc] - - [0x65F70, asm, libultra/os/startthread] - - [0x660C0, asm, libultra/io/visetxscale] - - [0x661F0, asm, libultra/io/visetyscale] - - [0x66250, asm, libultra/libc/llcvt] - - [0x66460, asm, libultra/al/synallocfx] - - [0x66500, asm, libultra/al/syndelete] - - [0x66510, asm, libultra/io/gbpakreadwrite] - - [0x666D0, asm, libultra/io/gbpakselectbank] - - [0x667A0, asm, libultra/io/aisetnextbuf] - - [0x66850, asm, libultra/io/ai] - - [0x66880, asm, libultra/io/conteepread] - - [0x66AD0, asm, libultra/io/vigetcurrframebuf] - - [0x66B10, asm, libultra/io/spsetpc] - - [0x66B50, asm, libultra/os/sethwinterrupt] + - [0x64A10, c, libultra/io/epirawwrite] + - [0x64B70, c, libultra/os/settimer] + - [0x64C50, c, libultra/libc/xldtob] + - [0x65710, c, libultra/libc/ldiv] + - [0x658A0, c, libultra/libc/xlitob] + - [0x65B40, c, libultra/io/sirawwrite] + - [0x65B90, c, libultra/io/spsetstat] + - [0x65BA0, c, libultra/io/spgetstat] + - [0x65BB0, bin, noppad_65BB0] + - [0x65BC0, c, libultra/io/vimgr] + - [0x65ED0, c, libultra/io/vigetcurrcontext] + - [0x65EE0, hasm, libultra/os/writebackdcacheall] + - [0x65F10, c, libultra/al/heapalloc] + - [0x65F70, c, libultra/os/startthread] + - [0x660C0, c, libultra/io/visetxscale] + - [0x661F0, c, libultra/io/visetyscale] + - [0x66250, c, libultra/libc/llcvt] + - [0x66460, c, libultra/al/synallocfx] + - [0x66500, c, libultra/al/syndelete] + - [0x66510, c, libultra/io/gbpakreadwrite] + - [0x666D0, c, libultra/io/gbpakselectbank] + - [0x667A0, c, libultra/io/aisetnextbuf] + - [0x66850, c, libultra/io/ai] + - [0x66880, c, libultra/io/conteepread] + - [0x66AD0, c, libultra/io/vigetcurrframebuf] + - [0x66B10, c, libultra/io/spsetpc] + - [0x66B50, c, libultra/os/sethwinterrupt] #- [0x66BC0, asm] - [0x66BC0, bin] # rest of rom part 1 @@ -327,6 +328,13 @@ segments: - [0x7B750, .data, libultra/al/env] - [0x7B890, .data, libultra/io/vi] - [0x7B900, bin, rom_data_7B900] + - [0x7B9F0, .data, libultra/io/gbpakreadid] + - [0x7BA40, .data, libultra/io/cartrominit] + - [0x7BA50, bin, rom_data_7BA50] + - [0x7BA60, .data, libultra/libc/xlitob] + - [0x7BA90, .data, libultra/io/vimgr] + - [0x7BAB0, .data, libultra/io/aisetnextbuf] + - [0x7BAC0, bin, rom_data_7BAC0] # Start of .rodata - [0x7BAC0, .rodata, rsp] # rsp.c rodata @@ -345,6 +353,9 @@ segments: - [0x7F130, .rodata, libultra/al/resample] - [0x7F180, .rodata, libultra/gu/cosf] - [0x7F1D0, bin, rom_rodata_7F1D0] + - [0x7F1E0, .rodata, libultra/libc/xldtob] + - [0x7F240, .rodata, libultra/libc/llcvt] + - [0x7F250, bin, rom_rodata_7F250] - [0x7F980] # .bss @@ -353,6 +364,8 @@ segments: - {vram: 0x80083CA0, type: .bss, name: unk_bss} - {vram: 0x80103880, type: .bss, name: libultra/gu/rotate} - {vram: 0x80103890, type: .bss, name: libultra/os/timerintr} + - {vram: 0x801038E4, type: .bss, name: libultra/io/cartrominit} + - {vram: 0x80103950, type: .bss, name: libultra/io/vimgr} # rest of the ROM - [0x7F980, bin] diff --git a/src/libultra/al/heapalloc.c b/src/libultra/al/heapalloc.c new file mode 100644 index 0000000..8a37808 --- /dev/null +++ b/src/libultra/al/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 +#include +#include + +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/src/libultra/al/synallocfx.c b/src/libultra/al/synallocfx.c new file mode 100644 index 0000000..5831062 --- /dev/null +++ b/src/libultra/al/synallocfx.c @@ -0,0 +1,31 @@ +/*==================================================================== + * 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/src/libultra/al/syndelete.c b/src/libultra/al/syndelete.c new file mode 100644 index 0000000..74abaa4 --- /dev/null +++ b/src/libultra/al/syndelete.c @@ -0,0 +1,26 @@ +/*==================================================================== + * 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/src/libultra/io/ai.c b/src/libultra/io/ai.c new file mode 100644 index 0000000..5e345dc --- /dev/null +++ b/src/libultra/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/src/libultra/io/aigetlen.c b/src/libultra/io/aigetlen.c new file mode 100644 index 0000000..6b83682 --- /dev/null +++ b/src/libultra/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/src/libultra/io/aisetnextbuf.c b/src/libultra/io/aisetnextbuf.c new file mode 100644 index 0000000..d789133 --- /dev/null +++ b/src/libultra/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; + + bptr = bufPtr; + + if (hdwrBugFlag) { + bptr -= 0x2000; + } + + if ((((u32)bufPtr + size) & 0x1fff) == 0) { + hdwrBugFlag = TRUE; + } else { + hdwrBugFlag = FALSE; + } + + if (__osAiDeviceBusy()) { + return -1; + } + + IO_WRITE(AI_DRAM_ADDR_REG, osVirtualToPhysical(bptr)); + IO_WRITE(AI_LEN_REG, size); + return 0; +} diff --git a/src/libultra/io/cartrominit.c b/src/libultra/io/cartrominit.c new file mode 100644 index 0000000..35d6e38 --- /dev/null +++ b/src/libultra/io/cartrominit.c @@ -0,0 +1,65 @@ +#include +#include "PR/os_internal.h" +#include "PR/R4300.h" +#include "PR/rcp.h" + +OSPiHandle __CartRomHandle; +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/src/libultra/io/conteepread.c b/src/libultra/io/conteepread.c new file mode 100644 index 0000000..23c8ad2 --- /dev/null +++ b/src/libultra/io/conteepread.c @@ -0,0 +1,105 @@ +#include +#include "PR/rcp.h" +#include "ultra64/controller.h" +#include "siint.h" + +void __osPackEepReadData(u8 address); +extern OSPifRam __osEepPifRam; +extern s32 __osEepromRead16K; + +#define CONT_RANGE_ERROR -1 + +s32 osEepromRead(OSMesgQueue *mq, u8 address, u8 *buffer) +{ + s32 ret; + int i; + u16 type; + u8 *ptr; + OSContStatus sdata; + __OSContEepromFormat eepromformat; + ret = 0; + i = 0; + ptr = (u8 *)&__osEepPifRam.ramarray; + __osSiGetAccess(); + ret = __osEepStatus(mq, &sdata); + + if (ret == 0) { + type = sdata.type & (CONT_EEPROM | CONT_EEP16K); + + switch (type) { + case CONT_EEPROM: + // @bug: Should be > EEPROM_MAXBLOCKS + if (address >= EEPROM_MAXBLOCKS) { + ret = -1; + } + break; + case CONT_EEPROM | CONT_EEP16K: + // @bug: Should be > EEP16K_MAXBLOCKS + if (address >= EEP16K_MAXBLOCKS) { + ret = -1; + } + break; + default: + if (1); + 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); + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osEepPifRam); + __osContLastCmd = CONT_CMD_READ_EEPROM; + osRecvMesg(mq, NULL, OS_MESG_BLOCK); + + for (i = 0; i < 4; i++) { + 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; +} + +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/src/libultra/io/contramread.c b/src/libultra/io/contramread.c new file mode 100644 index 0000000..cc85547 --- /dev/null +++ b/src/libultra/io/contramread.c @@ -0,0 +1,73 @@ +#include +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "ultra64/controller.h" + +extern s32 __osPfsLastChannel; + +#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_MEMPACK || __osPfsLastChannel != channel) { + __osContLastCmd = CONT_CMD_READ_MEMPACK; + __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_MEMPACK_TX; + READFORMAT(ptr)->rxsize = CONT_CMD_READ_MEMPACK_RX; + READFORMAT(ptr)->cmd = CONT_CMD_READ_MEMPACK; + READFORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSContRamReadFormat)] = CONT_CMD_END; + } else { + ptr += channel; + } + + READFORMAT(ptr)->hi = address >> 3; + READFORMAT(ptr)->lo = (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 = ((((__OSContRamReadFormat*)ptr)->rxsize & 0xC0) >> 4); + + 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/src/libultra/io/contramwrite.c b/src/libultra/io/contramwrite.c new file mode 100644 index 0000000..8499892 --- /dev/null +++ b/src/libultra/io/contramwrite.c @@ -0,0 +1,74 @@ +#include +#include "PR/os_internal.h" +#include "PR/rcp.h" +#include "ultra64/controller.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 != PFS_FORCE) && (address < PFS_LABEL_AREA) && (address != 0)) { + return 0; + } + + __osSiGetAccess(); + + do { + ptr = (u8*)(&__osPfsPifRam.ramarray); + + if (__osContLastCmd != CONT_CMD_WRITE_MEMPACK || __osPfsLastChannel != channel) { + __osContLastCmd = CONT_CMD_WRITE_MEMPACK; + __osPfsLastChannel = channel; + + // clang-format off + for (i = 0; i < channel; i++) { *ptr++ = 0; } + // clang-format on + + __osPfsPifRam.pifstatus = 1; + + READFORMAT(ptr)->dummy = CONT_CMD_NOP; + READFORMAT(ptr)->txsize = CONT_CMD_WRITE_MEMPACK_TX; + READFORMAT(ptr)->rxsize = CONT_CMD_WRITE_MEMPACK_RX; + READFORMAT(ptr)->cmd = CONT_CMD_WRITE_MEMPACK; + READFORMAT(ptr)->datacrc = 0xFF; + + ptr[sizeof(__OSContRamReadFormat)] = CONT_CMD_END; + } else { + ptr += channel; + } + READFORMAT(ptr)->hi = address >> 3; + READFORMAT(ptr)->lo = ((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 = ((((__OSContRamReadFormat*)ptr)->rxsize & 0xC0) >> 4); + if (!ret) { + if (crc != ((__OSContRamReadFormat*)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; +} diff --git a/src/libultra/io/crc.c b/src/libultra/io/crc.c new file mode 100644 index 0000000..7d39201 --- /dev/null +++ b/src/libultra/io/crc.c @@ -0,0 +1,96 @@ +#include "PR/os_internal.h" + +u8 __osContAddressCrc(u16 inaddr) +{ + u32 crc; + u32 mask; + u32 addr = inaddr; + + crc = 0; + + for (mask = 0x400; mask != 0; mask >>= 1) { + crc *= 2; + + if (addr & mask) { + if (crc & 0x20) { + crc ^= 20; + } else { + crc++; + } + } else { + if (crc & 0x20) { + crc ^= 21; + } + } + } + + crc <<= 1; + + if (crc & 0x20) { + crc ^= 21; + } + + crc <<= 1; + + if (crc & 0x20) { + crc ^= 21; + } + + crc <<= 1; + + if (crc & 0x20) { + crc ^= 21; + } + + crc <<= 1; + + if (crc & 0x20) { + crc ^= 21; + } + + crc <<= 1; + + if (crc & 0x20) { + crc ^= 21; + } + + return crc & 0x1f; +} + +u8 __osContDataCrc(u8 *data) +{ + u32 i; + u32 mask; + u32 crc = 0; + + for (i = 32; i != 0; i--) { + for (mask = 0x80; mask != 0; mask >>= 1) { + crc *= 2; + + if (*data & mask) { + if (crc & 0x100) { + crc ^= 132; + } else { + crc++; + } + } else { + if (crc & 0x100) { + crc ^= 133; + } + } + } + + data++; + } + + do { + crc <<= 1; + + if (crc & 0x100) { + crc ^= 133; + } + i++; + } while (i < 8); + + return crc; +} diff --git a/src/libultra/io/epirawwrite.c b/src/libultra/io/epirawwrite.c new file mode 100644 index 0000000..f5798b1 --- /dev/null +++ b/src/libultra/io/epirawwrite.c @@ -0,0 +1,58 @@ +#include +#include "piint.h" + +s32 osEPiRawWriteIo(OSPiHandle *handle, u32 devAddr, u32 data) +{ + u32 stat = IO_READ(PI_STATUS_REG); + + while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) { + stat = IO_READ(PI_STATUS_REG); + } + + if (__osCurrentHandle[handle->domain]->type != handle->type) { + OSPiHandle *cHandle = __osCurrentHandle[handle->domain]; + + if (handle->domain == PI_DOMAIN1) { + if (cHandle->latency != handle->latency) { + IO_WRITE(PI_BSD_DOM1_LAT_REG, handle->latency); + } + + if (cHandle->pageSize != handle->pageSize) { + IO_WRITE(PI_BSD_DOM1_PGS_REG, handle->pageSize); + } + + if (cHandle->relDuration != handle->relDuration) { + IO_WRITE(PI_BSD_DOM1_RLS_REG, handle->relDuration); + } + + if (cHandle->pulse != handle->pulse) { + IO_WRITE(PI_BSD_DOM1_PWD_REG, handle->pulse); + } + } else { + if (cHandle->latency != handle->latency) { + IO_WRITE(PI_BSD_DOM2_LAT_REG, handle->latency); + } + + if (cHandle->pageSize != handle->pageSize) { + IO_WRITE(PI_BSD_DOM2_PGS_REG, handle->pageSize); + } + + if (cHandle->relDuration != handle->relDuration) { + IO_WRITE(PI_BSD_DOM2_RLS_REG, handle->relDuration); + } + + if (cHandle->pulse != handle->pulse) { + IO_WRITE(PI_BSD_DOM2_PWD_REG, handle->pulse); + } + } + + cHandle->type = handle->type; + cHandle->latency = handle->latency; + cHandle->pageSize = handle->pageSize; + cHandle->relDuration = handle->relDuration; + cHandle->pulse = handle->pulse; + } + + IO_WRITE(handle->baseAddress | devAddr, data); + return 0; +} diff --git a/src/libultra/io/epiwrite.c b/src/libultra/io/epiwrite.c new file mode 100644 index 0000000..e5c7a33 --- /dev/null +++ b/src/libultra/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/src/libultra/io/gbpakreadid.c b/src/libultra/io/gbpakreadid.c new file mode 100644 index 0000000..3585c99 --- /dev/null +++ b/src/libultra/io/gbpakreadid.c @@ -0,0 +1,91 @@ +#include +#include "ultra64/controller.h" +#include "siint.h" + +extern void _bcopy(void *, void *, u32); + +u32 g_OsGbNintendoData[] = { + 0xceed6666, 0xcc0d000b, 0x03730083, 0x000c000d, + 0x0008111f, 0x8889000e, 0xdccc6ee6, 0xddddd999, + 0xbbbb6763, 0x6e0eeccc, 0xdddc999f, 0xbbb9333e, +}; + +u8 g_OsGbCartVersions[] = { + 0x00, 0x01, 0x01, 0x01, + 0xff, 0x02, 0x02, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x03, + 0x03, 0x03, 0x03, 0x03, +}; + +s32 osGbpakReadId(OSPfs *pfs, OSGbpakId *id, u8 *status) +{ + s32 i; + s32 ret; + u8 sum; + u8 buffer[0x60]; + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = osGbpakGetStatus(pfs, status); + } + + if (ret == PFS_ERR_NEW_GBCART) { + return PFS_ERR_CONTRFAIL; + } + + if (ret == 0) { + if ((*status & OS_GBPAK_POWER) == 0) { + ret = osGbpakPower(pfs, OS_GBPAK_POWER_ON); + + if (ret != 0) { + return ret; + } + } + + ret = osGbpakReadWrite(pfs, PFS_READ, 0x100, buffer, 0x60); + + if (ret != 0) { + return ret; + } + + ret = osGbpakGetStatus(pfs, status); + + if (ret == PFS_ERR_NEW_GBCART) { + ret = PFS_ERR_CONTRFAIL; + } + + if (ret != 0) { + return ret; + } + + // Compare id->nintendo_chr with expected data + if (bcmp(g_OsGbNintendoData, &buffer[4], sizeof(id->nintendo_chr)) != 0) { + return PFS_ERR_CONTRFAIL; + } + + // Sum game_title through to isum + sum = 0; + + for (i = 0x34; i < 0x4e; i++) { + sum += buffer[i]; + } + + sum = (sum + 25) & 0xff; + + if (sum != 0) { + return PFS_ERR_CONTRFAIL; + } + + _bcopy(buffer, id, sizeof(OSGbpakId)); + + if (id->cart_type < 20) { + pfs->version = g_OsGbCartVersions[id->cart_type]; + } + + pfs->dir_size = id->ram_size; + } + + return ret; +} diff --git a/src/libultra/io/gbpakreadwrite.c b/src/libultra/io/gbpakreadwrite.c new file mode 100644 index 0000000..d1c8436 --- /dev/null +++ b/src/libultra/io/gbpakreadwrite.c @@ -0,0 +1,77 @@ +#include +#include "ultra64/controller.h" + +s32 osGbpakReadWrite(OSPfs *pfs, u16 flag, u16 address, u8 *buffer, u16 size) +{ + s32 i; + s32 ret; + u8 bank; + u16 addr; + + bank = address >> 14; + + if (bank != pfs->banks) { + ret = __osGbpakSelectBank(pfs, bank); + + if (ret != 0) { + return ret; + } + } + + size = size >> 5; + address = (address | 0xc000) >> 5; + + if (flag == PFS_WRITE) { + for (i = 0; i < size; i++) { + ret = __osContRamWrite(pfs->queue, pfs->channel, address, buffer, 0); + + if (ret != 0) { + break; + } + + address++; + + if (address >= 0x800 && i < size - 1) { + bank++; + ret = __osGbpakSelectBank(pfs, bank); + + if (ret != 0) { + break; + } + + address = 0x600; + } + + buffer += BLOCKSIZE; + } + } else { + for (i = 0; i < size; i++) { + ret = __osContRamRead(pfs->queue, pfs->channel, address, buffer); + + if (ret != 0) { + break; + } + + address++; + + if (address >= 0x800 && i < size - 1) { + bank++; + ret = __osGbpakSelectBank(pfs, bank); + + if (ret != 0) { + break; + } + + address = 0x600; + } + + buffer += BLOCKSIZE; + } + } + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + + return ret; +} diff --git a/src/libultra/io/gbpakselectbank.c b/src/libultra/io/gbpakselectbank.c new file mode 100644 index 0000000..27de904 --- /dev/null +++ b/src/libultra/io/gbpakselectbank.c @@ -0,0 +1,42 @@ +#include +#include "ultra64/controller.h" +#include "siint.h" + +s32 __osGbpakSelectBank(OSPfs *pfs, u8 bank) +{ + s32 ret; + s32 i; + u8 buffer[32]; + s32 j; + + if (bank >= 3) { + return PFS_ERR_INVALID; + } + + for (i = 0; i < 32; i+=4) { + buffer[i+0] = bank; + buffer[i+1] = bank; + buffer[i+2] = bank; + buffer[i+3] = bank; + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, 0x500, (u8 *)buffer, 0); + + if (ret == PFS_ERR_NEW_PACK) { + ret = osGbpakInit(pfs->queue, pfs, pfs->channel); + + if (ret == 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, 0x500, (u8 *)buffer, 0); + + if (ret == PFS_ERR_NEW_PACK) { + ret = PFS_ERR_CONTRFAIL; + } + } + } + + if (ret == 0) { + pfs->banks = bank; + } + + return ret; +} diff --git a/src/libultra/io/pfsselectbank.c b/src/libultra/io/pfsselectbank.c new file mode 100644 index 0000000..4c03254 --- /dev/null +++ b/src/libultra/io/pfsselectbank.c @@ -0,0 +1,24 @@ +#include +#include "ultra64/controller.h" + +s32 __osPfsSelectBank(OSPfs *pfs, u8 bank) +{ + u8 temp[8][4]; + int i, j; + s32 ret; + ret = 0; + + for (i = 0; i < 8; i++) { + for(j = 0; j < 4; j++) { + temp[i][j] = bank; + } + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, 1024, (u8*)temp, FALSE); + + if (ret == 0) { + pfs->activebank = bank; + } + + return ret; +} diff --git a/src/libultra/io/sirawwrite.c b/src/libultra/io/sirawwrite.c new file mode 100644 index 0000000..9967c1d --- /dev/null +++ b/src/libultra/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/src/libultra/io/spgetstat.c b/src/libultra/io/spgetstat.c new file mode 100644 index 0000000..0cdfda6 --- /dev/null +++ b/src/libultra/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/src/libultra/io/spsetpc.c b/src/libultra/io/spsetpc.c new file mode 100644 index 0000000..dce0b5d --- /dev/null +++ b/src/libultra/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/src/libultra/io/spsetstat.c b/src/libultra/io/spsetstat.c new file mode 100644 index 0000000..2ab47e0 --- /dev/null +++ b/src/libultra/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/src/libultra/io/vigetcurrcontext.c b/src/libultra/io/vigetcurrcontext.c new file mode 100644 index 0000000..729d902 --- /dev/null +++ b/src/libultra/io/vigetcurrcontext.c @@ -0,0 +1,9 @@ +#include +#include "viint.h" + +// TODO: this comes from a header +#ident "$Revision: 1.17 $" + +__OSViContext *__osViGetCurrentContext(void) { + return __osViCurr; +} diff --git a/src/libultra/io/vigetcurrframebuf.c b/src/libultra/io/vigetcurrframebuf.c new file mode 100644 index 0000000..987e86b --- /dev/null +++ b/src/libultra/io/vigetcurrframebuf.c @@ -0,0 +1,10 @@ +#include +#include "viint.h" + +void *osViGetCurrentFramebuffer(void) { + register u32 saveMask = __osDisableInt(); + void *framep = __osViCurr->framep; + + __osRestoreInt(saveMask); + return framep; +} diff --git a/src/libultra/io/vimgr.c b/src/libultra/io/vimgr.c new file mode 100644 index 0000000..0377d64 --- /dev/null +++ b/src/libultra/io/vimgr.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include "viint.h" +#include "../os/osint.h" + +#define ARRLEN(x) ((s32)(sizeof(x) / sizeof(x[0]))) + +OSDevMgr __osViDevMgr = {0}; +u32 __additional_scanline = 0; +static OSThread viThread; +static unsigned char viThreadStack[OS_VIM_STACKSIZE]; +static OSMesgQueue viEventQueue; +static OSMesg viEventBuf[5]; +static OSIoMesg viRetraceMsg; +static OSIoMesg viCounterMsg; + +static void viMgrMain(void *arg); +void osCreateViManager(OSPri pri) +{ + u32 savedMask; + OSPri oldPri; + OSPri myPri; + + 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/src/libultra/io/visetevent.c b/src/libultra/io/visetevent.c new file mode 100644 index 0000000..589647a --- /dev/null +++ b/src/libultra/io/visetevent.c @@ -0,0 +1,14 @@ +#include +#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/src/libultra/io/visetspecial.c b/src/libultra/io/visetspecial.c new file mode 100644 index 0000000..e8f90b8 --- /dev/null +++ b/src/libultra/io/visetspecial.c @@ -0,0 +1,48 @@ +#include +#include +#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/src/libultra/io/visetxscale.c b/src/libultra/io/visetxscale.c new file mode 100644 index 0000000..328987c --- /dev/null +++ b/src/libultra/io/visetxscale.c @@ -0,0 +1,16 @@ +#include +#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/src/libultra/io/visetyscale.c b/src/libultra/io/visetyscale.c new file mode 100644 index 0000000..525e0eb --- /dev/null +++ b/src/libultra/io/visetyscale.c @@ -0,0 +1,13 @@ +#include +#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/src/libultra/libc/ldiv.c b/src/libultra/libc/ldiv.c new file mode 100644 index 0000000..3a7d57c --- /dev/null +++ b/src/libultra/libc/ldiv.c @@ -0,0 +1,31 @@ +#include + +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; +} + +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; +} diff --git a/src/libultra/libc/llcvt.c b/src/libultra/libc/llcvt.c new file mode 100644 index 0000000..2c423dd --- /dev/null +++ b/src/libultra/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/src/libultra/libc/xldtob.c b/src/libultra/libc/xldtob.c new file mode 100644 index 0000000..b032e57 --- /dev/null +++ b/src/libultra/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/src/libultra/libc/xlitob.c b/src/libultra/libc/xlitob.c new file mode 100644 index 0000000..f297df4 --- /dev/null +++ b/src/libultra/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/src/libultra/os/sethwinterrupt.c b/src/libultra/os/sethwinterrupt.c new file mode 100644 index 0000000..0fc9d30 --- /dev/null +++ b/src/libultra/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/src/libultra/os/settime.c b/src/libultra/os/settime.c new file mode 100644 index 0000000..5bae2a2 --- /dev/null +++ b/src/libultra/os/settime.c @@ -0,0 +1,6 @@ +#include "PR/os_internal.h" +#include "osint.h" + +void osSetTime(OSTime time) { + __osCurrentTime = time; +} diff --git a/src/libultra/os/settimer.c b/src/libultra/os/settimer.c new file mode 100644 index 0000000..7d10f9e --- /dev/null +++ b/src/libultra/os/settimer.c @@ -0,0 +1,27 @@ +#include +#include "osint.h" + +int osSetTimer(OSTimer *t, OSTime value, OSTime interval, OSMesgQueue *mq, OSMesg msg) +{ + OSTime time; + + t->next = NULL; + t->prev = NULL; + t->interval = interval; + + if (value != 0) { + t->value = value; + } else { + t->value = interval; + } + + t->mq = mq; + t->msg = msg; + time = __osInsertTimer(t); + + if (__osTimerList->next == t) { + __osSetTimerIntr(time); + } + + return 0; +} diff --git a/src/libultra/os/startthread.c b/src/libultra/os/startthread.c new file mode 100644 index 0000000..0358ebb --- /dev/null +++ b/src/libultra/os/startthread.c @@ -0,0 +1,33 @@ +#include +#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/src/libultra/os/yieldthread.c b/src/libultra/os/yieldthread.c new file mode 100644 index 0000000..f4ed7c5 --- /dev/null +++ b/src/libultra/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/tools/symbol_addrs.txt b/tools/symbol_addrs.txt index 418f4a8..5a07750 100644 --- a/tools/symbol_addrs.txt +++ b/tools/symbol_addrs.txt @@ -375,4 +375,16 @@ _getVol = 0x80061238; osViModePalLan1 = 0x8007AD00; osViModeMpalLan1 = 0x8007ADA0; osViModeNtscLan1 = 0x8007AD50; -__additional_scanline = 0x8007AEAC; \ No newline at end of file +g_OsGbNintendoData = 0x8007ADF0; +g_OsGbCartVersions = 0x8007AE20; +__CartRomHandle = 0x801038D0; +__osPfsLastChannel = 0x8007AE50; +__osViDevMgr = 0x8007AE90; +__additional_scanline = 0x8007AEAC; +viThread = 0x80103950; +viThreadStack = 0x80103B00; +viEventQueue = 0x80104B00; +viEventBuf = 0x80104B18; +viRetraceMsg = 0x80104B30; +viCounterMsg = 0x80104B48; +__osHwIntTable = 0x80079650; \ No newline at end of file