V1.0
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
/* 0x0012DB68 snd_StartSoundSystem (assembly in the decomp): binds the IOP sound driver, which is host code here (host/src/rac1/snd989.c). */
|
||||
#include "common.h"
|
||||
s32 func_0012DB68(void) { uya_log("989snd: sound system started (host IOP driver)"); return 0; }
|
||||
@@ -0,0 +1,4 @@
|
||||
/* 0x0012DDC0 snd_FlushSoundCommands: delivers owed replies, finished bank loads and stream-safe CD reads; nothing stays queued (host/src/rac1/snd989.c) */
|
||||
#include "common.h"
|
||||
s32 rac1_snd_flush(void);
|
||||
s32 func_0012DDC0(void) { return rac1_snd_flush(); }
|
||||
@@ -0,0 +1,3 @@
|
||||
/* 0x0012DFB0 snd_GotReturns: replies are always in */
|
||||
#include "common.h"
|
||||
s32 func_0012DFB0(void) { return 1; }
|
||||
@@ -0,0 +1,11 @@
|
||||
/* 0x0012E060 snd_BankLoadByLoc(lsn, offset): the IOP loads a sound bank from the disc. Returns a bank handle (0 on failure). */
|
||||
#include "common.h"
|
||||
u32 rac1_snd_bank_load_lsn(s32 lsn, s32 off);
|
||||
u32 func_0012E060(s32 lsn, s32 off)
|
||||
{
|
||||
u32 h;
|
||||
*(volatile s32 *)0x0015ED88 = 0;
|
||||
h = rac1_snd_bank_load_lsn(lsn, off);
|
||||
uya_log("989snd: bank at LSN %d (+%d): handle %08X", lsn, off, h);
|
||||
return h;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* 0x0012E1C8 snd_BankLoadFromEE_CB(addr, callback, arg): command 0x57. The bank is loaded at once; as in the
|
||||
* library, the reply word (the bank handle) lands in D_0015EE00 and snd_FlushSoundCommands calls the callback. */
|
||||
#include "common.h"
|
||||
u32 rac1_snd_bank_load_ee(u32 addr);
|
||||
void func_0012E1C8(s32 addr, void *cb, s64 arg)
|
||||
{
|
||||
*(volatile s32 *)0x0015ED88 = 0;
|
||||
if (*(volatile s32 *)0x0015EDC8 != 0) { uya_log("989snd: bank load from EE while another is pending"); return; }
|
||||
*(volatile s32 *)0x0015EDD0 = (s32)cb;
|
||||
*(volatile s64 *)0x0015EDD8 = arg;
|
||||
*(volatile u32 *)0x0015EE00 = rac1_snd_bank_load_ee((u32)addr);
|
||||
*(volatile s32 *)0x0015EDC8 = 1;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/* 0x0012E688 snd_SendIOPCommandAndWait(cmd, size, data): to the host's sound driver (host/src/rac1/snd989.c) */
|
||||
#include "common.h"
|
||||
s32 rac1_snd_command(s32 cmd, s32 size, const void *data);
|
||||
s32 func_0012E688(s32 cmd, s32 size, void *data) { return rac1_snd_command(cmd, size, data); }
|
||||
@@ -0,0 +1,9 @@
|
||||
/* 0x0012E820 snd_SendIOPCommandNoWait(cmd, size, data, callback, arg): the reply goes to the callback at the next flush */
|
||||
#include "common.h"
|
||||
s32 rac1_snd_command(s32 cmd, s32 size, const void *data);
|
||||
void rac1_snd_owe(void *fn, s64 arg, s32 result);
|
||||
void func_0012E820(s32 cmd, s32 size, void *data, void *cb, s64 arg)
|
||||
{
|
||||
s32 r = rac1_snd_command(cmd, size, data);
|
||||
rac1_snd_owe(cb, arg, r);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
/* 0x0012EB18 snd_SendCurrentBatch (assembly in the decomp): commands are handled when sent */
|
||||
#include "common.h"
|
||||
void func_0012EB18(void) {}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* 0x0012F4A8 wad: reads level arg0's header (0x2434 bytes) from the sector in
|
||||
* the table of contents (D_0013A548, 8 bytes per level) into D_0013A5E0.
|
||||
* Same as the game's (src/core/wad.c), plus a testing switch:
|
||||
* UYA_LEVEL=n (or n@v, see host/src/rac1/boot.c) makes the first level the
|
||||
* game loads (level 0) level n instead, and sets the current level
|
||||
* (D_0015EE84) to n to match. Without UYA_LEVEL nothing changes. */
|
||||
#include "common.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
extern int func_00121750(int, int, void *, void *);
|
||||
extern int func_00120F30(int);
|
||||
extern void func_00122598(int);
|
||||
extern int func_00121930(void);
|
||||
|
||||
int func_0012F4A8(int arg0)
|
||||
{
|
||||
static int used;
|
||||
if (!used) {
|
||||
const char *e = getenv("UYA_LEVEL");
|
||||
used = 1;
|
||||
if (e && arg0 == 0) {
|
||||
arg0 = atoi(e);
|
||||
*(volatile s32 *)0x0015EE84 = arg0;
|
||||
uya_log("UYA_LEVEL: loading level %d instead of level 0 (testing)", arg0);
|
||||
}
|
||||
}
|
||||
char buf[0x2800];
|
||||
char hdr[4];
|
||||
const int *entry = (const int *)(uintptr_t)(0x0013A548 + arg0 * 8);
|
||||
hdr[0] = 0x20;
|
||||
hdr[1] = *(volatile unsigned char *)0x0015EE58;
|
||||
hdr[2] = 0;
|
||||
hdr[3] = 0;
|
||||
do {
|
||||
func_00121750(*entry, 5, buf, hdr);
|
||||
while (func_00120F30(1) != 0) func_00122598(0);
|
||||
} while (func_00121930() != 0);
|
||||
for (unsigned i = 0; i < 0x2434; i++) ((char *)(uintptr_t)0x0013A5E0)[i] = buf[i];
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9908 (fastfunc, hand-written): count down the timer *p.
|
||||
* 0 stays 0 and returns 1; otherwise it goes down by one and the result is 2
|
||||
* when it reaches 0, else 0. */
|
||||
s32 func_001F9908(s32 *p)
|
||||
{
|
||||
s32 x = *p;
|
||||
if (x == 0) return 1;
|
||||
x = (x > 1 ? x : 1) - 1;
|
||||
*p = x;
|
||||
return x > 0 ? 0 : 2;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9938 (fastfunc, hand-written): func_001F9908 on a 16-bit timer. */
|
||||
s32 func_001F9938(s16 *p)
|
||||
{
|
||||
s32 x = *p;
|
||||
if (x == 0) return 1;
|
||||
x = (x > 1 ? x : 1) - 1;
|
||||
*p = (s16)x;
|
||||
return x > 0 ? 0 : 2;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9968 (fastfunc, hand-written): 30 - plzcw(x), the index of the
|
||||
* highest bit that differs from the sign bit. */
|
||||
s32 func_001F9968(u32 x) { return 30 - uya_plzcw(x); }
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9978 (fastfunc, hand-written): `teq $0,$0`, the game's halt. */
|
||||
void func_001F9978(void) { uya_log("game halt (func_001F9978)"); }
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
/* 0x001F99B0 (fastfunc, hand-written): FastMemSet, a 32-bit pattern over n bytes (at least one word). */
|
||||
void func_001F99B0(u32 *p, u32 v, s32 n)
|
||||
{
|
||||
{ /* testing: UYA_LOADLOG=1 logs the scrubs of freed load buffers (0xDEADBEEF) */
|
||||
static int on = -1;
|
||||
if (on < 0) on = getenv("UYA_LOADLOG") != 0;
|
||||
if (on && v == 0xDEADBEEFu) { uint32_t uya_frame_count(void); uya_log("v%u fill %08X-%08X with DEADBEEF", uya_frame_count(), (u32)(uintptr_t)p, (u32)(uintptr_t)p + n); }
|
||||
}
|
||||
do { *p++ = v; n -= 4; } while (n > 0);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "common.h"
|
||||
/* 0x001F99D8 (fastfunc, hand-written): clear n bytes in quadwords (at least one). */
|
||||
void func_001F99D8(void *p, s32 n)
|
||||
{
|
||||
u8 *q = p;
|
||||
do { __builtin_memset(q, 0, 16); q += 16; n -= 16; } while (n > 0);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9A00 (fastfunc, hand-written): copy n bytes, by quadwords, words or
|
||||
* bytes depending on alignment. */
|
||||
void func_001F9A00(void *dst, const void *src, s32 n)
|
||||
{
|
||||
if (n > 0) __builtin_memmove(dst, src, (u32)n);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9A98 (fastfunc, hand-written): copy n bytes in quadwords (at least one). */
|
||||
void func_001F9A98(void *dst, const void *src, s32 n)
|
||||
{
|
||||
u8 *d = dst; const u8 *s = src;
|
||||
do { __builtin_memcpy(d, s, 16); d += 16; s += 16; n -= 16; } while (n > 0);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9AC0 (fastfunc, hand-written): dst = a | b over n bytes, in quadwords (at least one). */
|
||||
void func_001F9AC0(u32 *dst, const u32 *a, const u32 *b, s32 n)
|
||||
{
|
||||
do {
|
||||
for (int i = 0; i < 4; i++) dst[i] = a[i] | b[i];
|
||||
dst += 4; a += 4; b += 4; n -= 16;
|
||||
} while (n > 0);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9B70 (fastfunc, hand-written): abs(x) */
|
||||
s32 func_001F9B70(s32 x) { return x < 0 ? -x : x; }
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9D78 (fastfunc, VU0): do two spheres (xyz centre, w radius) overlap?
|
||||
* 1 when the squared distance is less than the squared sum of the radii. */
|
||||
s32 func_001F9D78(const f32 *a, const f32 *b)
|
||||
{
|
||||
f32 dx = a[0] - b[0], dy = a[1] - b[1], dz = a[2] - b[2], r = a[3] + b[3];
|
||||
return dx * dx + dy * dy + dz * dz - r * r < 0.0f ? 1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "common.h"
|
||||
/* 0x001F9E58 (fastfunc, VU0): clamp the length of src.xyz to max into dst.
|
||||
* Returns 1 when it was scaled, 0 when it was already short enough (or zero);
|
||||
* dst is only written when scaled. */
|
||||
s32 func_001F9E58(f32 *dst, const f32 *src, f32 max)
|
||||
{
|
||||
f32 l2 = src[0] * src[0] + src[1] * src[1] + src[2] * src[2];
|
||||
f32 len = __builtin_sqrtf(l2);
|
||||
if (len == 0.0f) return 0;
|
||||
if (max - len > 0.0f) return 0;
|
||||
f32 q = max / len;
|
||||
dst[0] = src[0] * q; dst[1] = src[1] * q; dst[2] = src[2] * q; dst[3] = src[3];
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
/* func_0020C468(src, dst): unpack a "WAD" compressed block (Insomniac's
|
||||
* LZ77 variant, close to LZO1X) and return the unpacked size.
|
||||
*
|
||||
* Ported from the UYA Wrapper (UYA's copy is func_0039B760). RAC1's retail
|
||||
* version is the same hand-written asm: it checks the "WAD" magic and streams
|
||||
* the input through the scratchpad in 0x2000-byte halves by DMA. Here the
|
||||
* input is read straight from memory; a far match with distance 0 and length
|
||||
* above 1 is the encoder's "go to the next 0x2000-byte chunk" marker, which in
|
||||
* a linear read means skipping to the next chunk boundary of the data (which
|
||||
* starts 0x10 bytes into the block). */
|
||||
#include "common.h"
|
||||
|
||||
s32 func_0020C468(u8 *src, u8 *dst)
|
||||
{
|
||||
u8 *start = dst;
|
||||
{ /* testing: UYA_LOADLOG=1 */
|
||||
static int on = -1;
|
||||
if (on < 0) on = getenv("UYA_LOADLOG") != 0;
|
||||
if (on) { uint32_t uya_frame_count(void); const char *rc_stack_scan(void); uya_log("v%u WAD unpack %08X -> %08X: %.3s; stack%s", uya_frame_count(), (u32)(uintptr_t)src, (u32)(uintptr_t)dst, (const char *)src, rc_stack_scan()); }
|
||||
}
|
||||
if (src[0] != 'W' || src[1] != 'A' || src[2] != 'D') return 0;
|
||||
u32 size = src[3] | (src[4] << 8) | (src[5] << 16) | ((u32)src[6] << 24);
|
||||
u8 *data = src + 0x10, *in = data, *end = src + size;
|
||||
u32 flag, n;
|
||||
u8 *m;
|
||||
|
||||
if (in[0] > 0x11) { /* leading literal run */
|
||||
n = *in++ - 0x11;
|
||||
while (n--) *dst++ = *in++;
|
||||
goto after_literals;
|
||||
}
|
||||
for (;;) {
|
||||
/* state A: a literal run may come next */
|
||||
if (in >= end) break;
|
||||
flag = *in++;
|
||||
if (flag < 0x10) {
|
||||
n = flag ? flag : *in++ + 0xF;
|
||||
n += 3;
|
||||
while (n--) *dst++ = *in++;
|
||||
after_literals:
|
||||
if (in >= end) break;
|
||||
flag = *in++;
|
||||
}
|
||||
/* a match */
|
||||
for (;;) {
|
||||
if (flag >= 0x40) {
|
||||
m = dst - 1 - ((flag >> 2) & 7);
|
||||
m -= *in++ << 3;
|
||||
n = (flag >> 5) - 1;
|
||||
} else if (flag >= 0x20) {
|
||||
n = flag & 0x1F;
|
||||
if (!n) n = *in++ + 0x1F;
|
||||
m = dst - 1 - ((in[0] >> 2) + (in[1] << 6));
|
||||
in += 2;
|
||||
} else if (flag >= 0x10) {
|
||||
m = dst - ((flag & 8) << 11);
|
||||
n = flag & 7;
|
||||
if (!n) n = *in++ + 7;
|
||||
m -= (in[0] >> 2) + (in[1] << 6);
|
||||
in += 2;
|
||||
if (m == dst) {
|
||||
if (n != 1) { /* next-chunk marker */
|
||||
u32 off = (u32)(in - data);
|
||||
in = data + ((off + 0x1FFF) & ~0x1FFFu);
|
||||
goto state_a;
|
||||
}
|
||||
goto trailing; /* distance 0, length 1: no copy */
|
||||
}
|
||||
m -= 0x4000;
|
||||
} else {
|
||||
uya_unimpl("func_0020C468: bad WAD stream");
|
||||
return (s32)(dst - start);
|
||||
}
|
||||
*dst++ = *m++;
|
||||
*dst++ = *m++;
|
||||
do { *dst++ = *m++; } while ((s32)--n > 0);
|
||||
trailing:
|
||||
n = in[-2] & 3; /* up to 3 literals after a match */
|
||||
if (!n) goto state_a;
|
||||
while (n--) *dst++ = *in++;
|
||||
if (in >= end) return (s32)(dst - start);
|
||||
flag = *in++;
|
||||
}
|
||||
state_a:;
|
||||
}
|
||||
return (s32)(dst - start);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/* 0x0022DBE8: SoundMasterVolumeInit (sound.c, still assembly in the decomp).
|
||||
* Ported from the assembly: clears the sound tables at 0x0013E650, starts
|
||||
* 989snd, sets playback mode, reverb and voice ranges, derives the six master
|
||||
* volumes from the option values at 0x0015EEEC/0x0015EEF0, starts the music
|
||||
* streamer (func_002161E0, which also registers the CD callback the
|
||||
* streaming loads wait on) and sets the volumes. */
|
||||
#include "common.h"
|
||||
|
||||
extern void func_0012DB68(void); /* snd_StartSoundSystem */
|
||||
extern void func_0012E380(s32); /* snd_SetPlaybackMode */
|
||||
extern void func_0012E3C0(s32, s32);
|
||||
extern void func_0012F0E8(s32, s32); /* snd_PreAllocReverbWorkArea */
|
||||
extern void func_0012E3F8(s32, s32, s32); /* snd_SetGroupVoiceRange */
|
||||
extern void func_0012E348(s32, s32); /* snd_SetMasterVolume */
|
||||
extern void func_002161E0(void); /* MusicStreamInit */
|
||||
|
||||
void func_0022DBE8(void)
|
||||
{
|
||||
u8 *b = (u8 *)0x0013E650;
|
||||
s32 vol, v8, v7;
|
||||
__builtin_memset(b, 0, 0x40);
|
||||
*(u32 *)(b + 0x40) = 0;
|
||||
*(u32 *)(b + 0x44) = 0;
|
||||
for (s32 k = 1; k <= 30; k++) { *(u32 *)(b + 0x70 * k) = 0; b[0x70 * k + 4] = 0; }
|
||||
func_0012DB68();
|
||||
func_0012E380(*(s32 *)0x0015EEE8 == 0);
|
||||
func_0012E3C0(0, 1);
|
||||
func_0012F0E8(2, 4);
|
||||
func_0012E3F8(1, 0x18, 0x2F);
|
||||
func_0012E3F8(2, 0x18, 0x2F);
|
||||
func_0012E3F8(4, 0x18, 0x2F);
|
||||
vol = *(s32 *)0x0015EEF0;
|
||||
v8 = vol * 8 / 10;
|
||||
v7 = vol * 7 / 10;
|
||||
*(s32 *)(b + 0x4C) = *(s32 *)0x0015EEEC;
|
||||
*(s32 *)(b + 0x48) = v8;
|
||||
*(s32 *)(b + 0x50) = v8;
|
||||
*(s32 *)(b + 0x54) = v7;
|
||||
*(s32 *)(b + 0x58) = v7;
|
||||
*(s32 *)(b + 0x5C) = vol;
|
||||
func_002161E0();
|
||||
for (s32 i = 0; i < 6; i++) func_0012E348(i, *(s32 *)(b + 0x48 + 4 * i));
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/* 0x0023B670: play a movie (src/game/movie/movie.c): (sector, size, buffer,
|
||||
* player state, language). The Sony sample player it runs (IPU, threads,
|
||||
* SPU, uncached buffers) is replaced by the host's MPEG-2 player
|
||||
* (host/src/movie/player.c); the language picks the movie's sound track. */
|
||||
#include "common.h"
|
||||
int uya_movie_play_track(u32 lsn, u32 bytes, int track);
|
||||
s32 func_0023B670(s32 sector, s32 size, s32 buf, s32 state, s32 lang)
|
||||
{
|
||||
(void)buf; (void)state;
|
||||
u32 bytes = (u32)size < 0x40000u ? (u32)size * 2048u : (u32)size; /* the table gives sectors */
|
||||
uya_movie_play_track((u32)sector, bytes, lang);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user