perfect_dark/src/game/savebuffer.c

616 lines
12 KiB
C

#include <ultra64.h>
#include "constants.h"
#include "game/tex.h"
#include "game/camera.h"
#include "game/savebuffer.h"
#include "game/gfxmemory.h"
#include "game/file.h"
#include "game/utils.h"
#include "bss.h"
#include "lib/vi.h"
#include "lib/main.h"
#include "lib/mtx.h"
#include "data.h"
#include "types.h"
#if VERSION >= VERSION_NTSC_1_0
Vp *var80070f10 = NULL;
#else
Vp var80070f10;
#endif
s32 var8009de90;
s32 var8009de94;
s32 var8009de98;
s32 var8009de9c;
void func0f0d4690(Mtxf *mtx)
{
struct coord pos;
mtx4LoadIdentity(mtx);
pos.x = -159.75f;
pos.y = PAL ? 136.25f : 120.25f;
pos.z = 0;
pos.x = (.5f - viGetWidth()) * 0.5f;
pos.y = (.5f + viGetHeight()) * 0.5f;
pos.z = 0;
mtx4SetTranslation(&pos, mtx);
mtx00015e4c(-1, mtx);
if (g_ScaleX == 2) {
mtx00015df0(2, mtx);
}
}
void func0f0d475c(Mtxf *mtx)
{
func0f0d4690(mtx);
mtx00015df0(0.1f, mtx);
mtx00015e4c(0.1f, mtx);
}
Gfx *func0f0d479c(Gfx *gdl)
{
Mtxf mtx;
Mtxf *mtx1;
Mtxf *mtx2;
mtx1 = gfxAllocateMatrix();
mtx2 = gfxAllocateMatrix();
mtx00016760();
func0f0d475c(&mtx);
mtxF2L(&mtx, mtx2);
mtx4LoadIdentity(&mtx);
guFrustumF(mtx.m,
-(f32) viGetWidth() * 0.5f, viGetWidth() * 0.5f,
-(f32) viGetHeight() * 0.5f, viGetHeight() * 0.5f,
10, 10000, 1);
mtxF2L(&mtx, mtx1);
mtx00016784();
gSPMatrix(gdl++, osVirtualToPhysical(mtx2), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPMatrix(gdl++, osVirtualToPhysical(mtx1), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
#if VERSION >= VERSION_NTSC_1_0
if (var80070f10 == NULL) {
u32 size = align16(sizeof(Vp));
var80070f10 = gfxAllocate(size);
if (var80070f10 != NULL) {
var80070f10->vp.vscale[0] = viGetWidth() << 1;
var80070f10->vp.vscale[1] = viGetHeight() << 1;
var80070f10->vp.vscale[2] = 1;
var80070f10->vp.vscale[3] = 0;
var80070f10->vp.vtrans[0] = viGetWidth() << 1;
var80070f10->vp.vtrans[1] = viGetHeight() << 1;
var80070f10->vp.vtrans[2] = 0x1ff;
var80070f10->vp.vtrans[3] = 0;
}
}
gSPViewport(gdl++, var80070f10);
#else
var80070f10.vp.vscale[0] = 640;
var80070f10.vp.vscale[1] = 480;
var80070f10.vp.vscale[2] = 640;
var80070f10.vp.vscale[3] = 0;
var80070f10.vp.vtrans[0] = 640;
var80070f10.vp.vtrans[1] = 480;
var80070f10.vp.vtrans[2] = 0x1ff;
var80070f10.vp.vtrans[3] = 0;
var80070f10.vp.vscale[0] = viGetWidth() << 1;
var80070f10.vp.vscale[1] = viGetHeight() << 1;
var80070f10.vp.vscale[2] = 1;
var80070f10.vp.vscale[3] = 0;
var80070f10.vp.vtrans[0] = viGetWidth() << 1;
var80070f10.vp.vtrans[1] = viGetHeight() << 1;
var80070f10.vp.vtrans[2] = 0x1ff;
var80070f10.vp.vtrans[3] = 0;
gSPViewport(gdl++, &var80070f10);
#endif
gDPPipeSync(gdl++);
return gdl;
}
Gfx *func0f0d49c8(Gfx *gdl)
{
gSPViewport(gdl++, OS_K0_TO_PHYSICAL(viGetCurrentPlayerViewport()));
gSPMatrix(gdl++, osVirtualToPhysical(camGetPerspectiveMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
return gdl;
}
Gfx *func0f0d4a3c(Gfx *gdl, s32 arg1)
{
Mtxf mtx;
Mtxf *mtxptr = gfxAllocateMatrix();
gDPPipeSync(gdl++);
if (arg1 == 0) {
texSelect(&gdl, &g_TexGeneralConfigs[6], 2, 0, 2, 1, NULL);
} else if (arg1 == 1) {
texSelect(&gdl, &g_TexGeneralConfigs[11], 2, 0, 2, 1, NULL);
}
gDPPipeSync(gdl++);
gDPSetCycleType(gdl++, G_CYC_1CYCLE);
gDPSetAlphaCompare(gdl++, G_AC_NONE);
gDPSetCombineMode(gdl++, G_CC_MODULATEIA, G_CC_MODULATEIA);
gSPSetGeometryMode(gdl++, G_SHADE);
gSPSetGeometryMode(gdl++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gdl++, G_CULL_BOTH);
gDPSetColorDither(gdl++, G_CD_DISABLE);
gDPSetTextureFilter(gdl++, G_TF_BILERP);
gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetTexturePersp(gdl++, G_TP_PERSP);
func0f0d4690(&mtx);
mtxF2L(&mtx, mtxptr);
gSPMatrix(gdl++, osVirtualToPhysical(mtxptr), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
return gdl;
}
Gfx *func0f0d4c80(Gfx *gdl)
{
Mtxf mtx;
Mtxf *mtxptr = gfxAllocateMatrix();
func0f0d4690(&mtx);
mtx00015df0(0.1f, &mtx);
mtx00015e4c(0.1f, &mtx);
mtxF2L(&mtx, mtxptr);
gSPMatrix(gdl++, osVirtualToPhysical(mtxptr), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
return gdl;
}
Gfx *menugfxDrawPlane(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2, s32 type)
{
u32 *colours;
struct gfxvtx *vertices;
f32 tmp1;
s16 a1;
s16 t1;
f32 sp34;
f32 sp30;
s16 sp2e;
s16 sp2c;
s16 sp2a;
s16 sp28;
s16 a1_2;
s16 scale = 10;
f32 tmp2;
static u32 depthsub = 1000;
static u32 txmul = 20;
static u32 rsub = 5;
colours = gfxAllocateColours(2);
vertices = gfxAllocateVertices(4);
sp34 = 1.0f;
sp30 = 1.0f;
mainOverrideVariable("txmul", &txmul);
if (y1 < var8009de90 && y2 < var8009de90) {
return gdl;
}
if (y1 > var8009de94 && y2 > var8009de94) {
return gdl;
}
if (y1 < var8009de90) {
y1 = var8009de90;
}
if (y2 < var8009de90) {
y2 = var8009de90;
}
if (y1 > var8009de94) {
y1 = var8009de94;
}
if (y2 > var8009de94) {
y2 = var8009de94;
}
sp2e = (x1 + y1) * txmul;
sp2c = (x2 + y2) * txmul;
sp2a = 0;
sp28 = 16384;
if (type == MENUPLANE_01) {
sp30 = 2.0f;
}
mainOverrideVariable("depthsub", &depthsub);
a1 = 200;
if (type == MENUPLANE_02 || type == MENUPLANE_03) {
if (type == MENUPLANE_02) {
sp2e = 0;
sp2c = 1024;
} else {
sp2e = 1024;
sp2c = 2048;
}
sp34 = 4.0f;
sp30 = 4.0f;
a1 = 6000;
}
if (type == MENUPLANE_08 || type == MENUPLANE_09 || type == MENUPLANE_11) {
sp2e = 0;
sp2c = 2048;
a1 = 2000;
sp34 = 4.0f;
sp30 = 4.0f;
if (type == MENUPLANE_09) {
sp30 = 2.0f;
}
}
if (type == MENUPLANE_04) {
a1 = 2000;
sp34 = 1.0f;
sp30 = 1.0f;
}
if (type == MENUPLANE_05 || type == MENUPLANE_06 || type == MENUPLANE_10) {
a1 = 1000;
sp2e = 0;
sp2c = 4096;
sp30 = 4.0f;
if (type == MENUPLANE_06) {
sp2e = 384;
sp2c = 4480;
sp30 = 8.0f;
} else if (type == MENUPLANE_10) {
sp2e = 384;
sp2c = 4480;
sp30 = 8.0f;
} else {
sp34 = 2.0f;
}
}
if (type == MENUPLANE_07) {
mainOverrideVariable("rsub", &rsub);
a1 = -rsub;
sp30 = 8.0f;
sp2a = 256;
sp28 = 0;
}
vertices[0].x = x1;
vertices[0].y = y1;
vertices[0].z = -10;
vertices[1].x = x2;
vertices[1].y = y2;
vertices[1].z = -10;
tmp1 = (f32) var8009de98 * a1 / scale;
tmp2 = (f32) var8009de9c * a1 / scale;
vertices[2].x = vertices[0].v[0] + (s16) tmp1;
vertices[2].y = vertices[0].v[1] + (s16) tmp2;
vertices[2].z = -10 - a1;
vertices[3].x = vertices[1].v[0] + (s16) tmp1;
vertices[3].y = vertices[1].v[1] + (s16) tmp2;
vertices[3].z = -10 - a1;
if (type == MENUPLANE_10) {
t1 = g_20SecIntervalFrac * sp34 * 64.0f * 32.0f;
} else {
t1 = (g_20SecIntervalFrac - 0.5f) * sp34 * 64.0f * 32.0f;
}
if (type == MENUPLANE_10) {
a1_2 = (g_20SecIntervalFrac - 0.5f) * sp30 * 64.0f * 32.0f;
} else {
a1_2 = g_20SecIntervalFrac * sp30 * 64.0f * 32.0f;
}
vertices[0].s = sp2e + t1;
vertices[0].t = sp2a + a1_2;
vertices[1].s = sp2c + t1;
vertices[1].t = sp2a + a1_2;
vertices[3].s = sp2c + t1;
vertices[3].t = sp28 + a1_2;
vertices[2].s = sp2e + t1;
vertices[2].t = sp28 + a1_2;
if (type == MENUPLANE_07) {
vertices[0].colour = 0;
vertices[1].colour = 0;
vertices[2].colour = 4;
vertices[3].colour = 4;
} else {
vertices[0].colour = 0;
vertices[1].colour = 4;
vertices[2].colour = 0;
vertices[3].colour = 4;
}
colours[0] = colour1;
colours[1] = colour2;
gDPSetColorArray(gdl++, osVirtualToPhysical(colours), 2);
gDPSetVerticeArray(gdl++, osVirtualToPhysical(vertices), 4);
gDPTri2(gdl++, 0, 1, 3, 3, 2, 0);
return gdl;
}
/**
* Write the specified amount of bits to the buffer, advancing the internal pointer.
*
* numbits is expected to be 32 or less.
*
* This function only sets bits to on and does not unset them.
*/
void savebufferOr(struct savebuffer *buffer, u32 value, s32 numbits)
{
u32 bit = 1 << (numbits - 1);
for (; bit; bit >>= 1) {
if (bit & value) {
s32 bitindex = buffer->bitpos % 8;
u8 mask = 1 << (7 - bitindex);
s32 byteindex = buffer->bitpos / 8;
buffer->bytes[byteindex] |= mask;
}
buffer->bitpos++;
}
}
#if VERSION >= VERSION_NTSC_1_0
/**
* Write the specified amount of bits to the buffer, advancing the internal pointer.
*
* numbits is expected to be 32 or less.
*/
void savebufferWriteBits(struct savebuffer *buffer, u32 value, s32 numbits, u8 *dst)
{
u32 bit = 1 << (numbits - 1);
for (; bit; bit >>= 1) {
s32 bitindex = buffer->bitpos % 8;
u8 mask = 1 << (7 - bitindex);
s32 byteindex = buffer->bitpos / 8;
if (bit & value) {
dst[byteindex] |= mask;
} else {
dst[byteindex] &= ~mask;
}
buffer->bitpos++;
}
}
#endif
/**
* Read the specified amount of bits from the buffer and return it as an
* integer, advancing the internal pointer.
*
* numbits is expected to be 32 or less.
*/
u32 savebufferReadBits(struct savebuffer *buffer, s32 numbits)
{
u32 bit = 1 << (numbits - 1);
u32 value = 0;
for (; bit; bit >>= 1) {
s32 bitindex = buffer->bitpos % 8;
u8 mask = 1 << (7 - bitindex);
s32 byteindex = buffer->bitpos / 8;
if (buffer->bytes[byteindex] & mask) {
value |= bit;
}
buffer->bitpos++;
}
return value;
}
void savebufferClear(struct savebuffer *buffer)
{
s32 i;
buffer->bitpos = 0;
for (i = 0; i < sizeof(buffer->bytes);) {
buffer->bytes[i] = 0;
i++;
}
}
void func0f0d5484(struct savebuffer *buffer, u8 *data, u8 len)
{
s32 i;
buffer->bitpos = 0;
for (i = 0; i < len; i++) {
buffer->bytes[i] = data[i];
}
}
void func0f0d54c4(struct savebuffer *buffer)
{
s32 tmp = buffer->bitpos;
if (tmp / 8 && buffer->bitpos);
}
/**
* Read a zero-terminated string from the buffer and move the buffer's internal
* pointer past the end of the string.
*/
void savebufferReadString(struct savebuffer *buffer, char *dst, bool addlinebreak)
{
bool foundnull = false;
s32 index = 0;
s32 i;
for (i = 0; i < 10; i++) {
s32 byte = savebufferReadBits(buffer, 8);
if (!foundnull) {
if (byte == '\0') {
foundnull = true;
} else {
dst[i] = byte;
index = i;
}
}
}
if (addlinebreak) {
index++;
dst[index] = '\n';
}
index++;
dst[index] = '\0';
}
void func0f0d55a4(struct savebuffer *buffer, char *src)
{
bool done = false;
s32 i;
for (i = 0; i < 10; i++) {
if (!done) {
if (src[i] == '\0') {
done = true;
} else if (src[i] == '\n') {
done = true;
} else {
u32 c = src[i];
savebufferOr(buffer, c, 8);
}
}
if (done) {
savebufferOr(buffer, '\0', 8);
}
}
}
void func0f0d564c(u8 *data, char *dst, bool addlinebreak)
{
struct savebuffer buffer;
func0f0d5484(&buffer, data, 10);
savebufferReadString(&buffer, dst, addlinebreak);
}
#if VERSION >= VERSION_NTSC_1_0
void func0f0d5690(u8 *dst, char *src)
{
struct savebuffer buffer;
bool done = false;
s32 i;
func0f0d5484(&buffer, dst, 10);
for (i = 0; i < 10; i++) {
if (!done) {
if (src[i] == '\0') {
done = true;
} else if (src[i] == '\n') {
done = true;
} else {
u32 c = src[i];
savebufferWriteBits(&buffer, c, 8, dst);
}
}
if (done) {
savebufferWriteBits(&buffer, '\0', 8, dst);
}
}
}
#endif
void savebufferWriteGuid(struct savebuffer *buffer, struct fileguid *guid)
{
savebufferOr(buffer, guid->fileid, 7);
savebufferOr(buffer, guid->deviceserial, 13);
}
void savebufferReadGuid(struct savebuffer *buffer, struct fileguid *guid)
{
guid->fileid = savebufferReadBits(buffer, 7);
guid->deviceserial = savebufferReadBits(buffer, 13);
}
void formatTime(char *dst, s32 time60, s32 precision)
{
s32 parts[5];
bool donefirst = false;
s32 len = 0;
s32 i;
parts[4] = time60 % 60 * 100 / 60; // hundredths
parts[3] = time60 / 60; // seconds
parts[2] = parts[3] / 60; // minutes
parts[1] = parts[2] / 60; // hours
parts[0] = parts[1] / 24; // days
parts[3] %= 60; // seconds
parts[2] %= 60; // minutes
parts[1] %= 24; // hours
for (i = 0; i <= precision; i++) {
if (donefirst) {
len += sprintf(&dst[len], ":%02d", parts[i]);
} else if (parts[i] != 0 || i >= TIMEPRECISION_MINUTES) {
len += sprintf(&dst[len], "%d", parts[i]);
donefirst = true;
}
}
}
#if VERSION >= VERSION_NTSC_1_0
void func0f0d5a7c(void)
{
var80070f10 = 0;
}
#endif