Browse Source

Fixes to make things work on real hardware again:

- Struct pointers need to be 32-bit aligned, otherwise the PS1 will crash
- For this purpose, some structs have been padded to make them a multiple of 4 bytes in size
- Vector data needs to be copied into scratch RAM at a 32-bit aligned address
tess_experiment
Nico de Poel 3 years ago
parent
commit
ddffc8860e
  1. 2
      common.h
  2. 2
      memory.c
  3. 2
      memory.h
  4. 6
      ps1bsp.h
  5. 2
      qmath.h
  6. BIN
      test.ps1bsp
  7. 50
      world.c

2
common.h

@ -2,6 +2,8 @@
#define __COMMON_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <psxapi.h>
#include <psxetc.h>

2
memory.c

@ -7,7 +7,7 @@ static char primbuff[2][PRIMBUFLEN]; // Primitive buffer, just a raw buffer of b
static char *nextpri;
static char *primbuff_bounds;
u_char* const scratchpad_root = (char*)0x1F800000;
u_char* const scratchpad = (char*)0x1F800000;
void *mem_scratch(char **scratch_offset, unsigned short size)
{

2
memory.h

@ -1,7 +1,7 @@
#ifndef __MEMORY_H__
#define __MEMORY_H__
extern u_char* const scratchpad_root; // Starting address of scratchpad memory
extern u_char* const scratchpad; // Starting address of scratchpad memory
/**
* @brief Allocate memory in the fast scratchpad RAM buffer.

6
ps1bsp.h

@ -66,13 +66,13 @@ typedef struct
typedef struct
{
unsigned short index;
unsigned char light;
unsigned short light;
} ps1bsp_facevertex_t;
typedef struct
{
unsigned short firstFaceVertex;
unsigned char numFaceVertices;
unsigned short numFaceVertices;
u_long drawFrame; // Which frame was this face last drawn on? Used to check if this face should be drawn.
} ps1bsp_face_t;
@ -80,7 +80,7 @@ typedef struct
typedef struct
{
SVECTOR normal;
short dist;
int dist;
} ps1bsp_plane_t;
typedef struct

2
qmath.h

@ -9,7 +9,7 @@ INLINE short m_dot12(const SVECTOR *a, const SVECTOR *b)
}
// TODO: worth a benchmark: is it faster to copy these vectors and use them from the stack, or to do six pointer dereferences?
INLINE short m_pointPlaneDist2(const VECTOR point2, const SVECTOR normal12, short dist2)
INLINE short m_pointPlaneDist2(const VECTOR point2, const SVECTOR normal12, int dist2)
{
int x = ((int)point2.vx * normal12.vx) >> 12;
int y = ((int)point2.vy * normal12.vy) >> 12;

BIN
test.ps1bsp

50
world.c

@ -22,10 +22,17 @@ static CVECTOR colors[] =
};
static const int numColors = sizeof(colors) / sizeof(CVECTOR);
// Set data pointers directly from an in-memory byte buffer
#define LOAD_CHUNK(type, dst, num, src, entry) \
dst = (type*)((src) + (entry).offset); \
num = (entry).size / sizeof(type);
// Allocate memory per chunk and copy data from a byte buffer
// #define LOAD_CHUNK(type, dst, num, src, entry) \
// dst = (type*)malloc((entry).size); \
// memcpy(dst, (src) + (entry).offset, (entry).size); \
// num = (entry).size / sizeof(type);
void world_load(const u_long *data, world_t *world)
{
const char *bytes = (const char*)data;
@ -214,12 +221,11 @@ static INLINE void drawface_quad_strip(const ps1bsp_face_t *face, SVECTOR *vecs)
}
}
static void world_drawface(const world_t *world, const ps1bsp_face_t *face, u_char *scratchptr)
static void world_drawface(const world_t *world, const ps1bsp_face_t *face)
{
const CVECTOR *col = &colors[(u_long)face % numColors];
SVECTOR *vecs = (SVECTOR*)scratchptr;
// scratchptr += sizeof(SVECTOR) * face->numFaceVertices; // No need to move the scratchpad pointer right now
SVECTOR *vecs = (SVECTOR*)(scratchpad + 256);
// Copy this face's vertices into scratch RAM for fast reuse
// TODO: this is the main performance bottleneck right now!
@ -237,7 +243,7 @@ static void world_drawface(const world_t *world, const ps1bsp_face_t *face, u_ch
drawface_quad_strip(face, vecs);
}
static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs, u_char *scratchptr)
static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs)
{
u_long frameNum = time_getFrameNumber();
@ -259,7 +265,7 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs, u_c
if (face->drawFrame == frameNum)
continue;
world_drawface(world, face, scratchptr);
world_drawface(world, face);
face->drawFrame = frameNum;
}
@ -276,7 +282,7 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs, u_c
// if (face->drawFrame == frameNum)
// continue;
// world_drawface(world, face, scratchptr);
// world_drawface(world, face);
// face->drawFrame = frameNum;
// }
@ -286,21 +292,21 @@ static void world_drawnode(const world_t *world, short nodeIdx, u_char *pvs, u_c
// Draw child nodes in front-to-back order; adding faces to the OT will reverse the drawing order
if (dist > 0)
{
world_drawnode(world, node->front, pvs, scratchptr);
world_drawnode(world, node->back, pvs, scratchptr);
world_drawnode(world, node->front, pvs);
world_drawnode(world, node->back, pvs);
}
else
{
world_drawnode(world, node->back, pvs, scratchptr);
world_drawnode(world, node->front, pvs, scratchptr);
world_drawnode(world, node->back, pvs);
world_drawnode(world, node->front, pvs);
}
}
// Decompress PVS data for the given leaf ID and store it in scratch RAM at the given scratch pointer location.
// Returns the memory location of decompressed PVS data, and moves the scratch pointer forward.
static u_char *world_loadVisData(const world_t *world, u_short leafIdx, u_char **scratchptr)
// Decompress PVS data for the given leaf ID and store it in RAM at the given buffer pointer location.
// Returns the memory location of decompressed PVS data, and moves the buffer pointer forward.
static u_char *world_loadVisData(const world_t *world, u_short leafIdx, u_char **buffer)
{
u_char *head = *scratchptr;
u_char *head = *buffer;
u_char *tail = head;
const ps1bsp_leaf_t *leaf = &world->leaves[leafIdx];
@ -324,13 +330,13 @@ static u_char *world_loadVisData(const world_t *world, u_short leafIdx, u_char *
}
}
*scratchptr = tail;
*buffer = tail;
return head;
}
static u_char *world_noVisData(const world_t *world, u_char **scratchptr)
static u_char *world_noVisData(const world_t *world, u_char **buffer)
{
u_char *head = *scratchptr;
u_char *head = *buffer;
u_char *tail = head;
for (int l = 1; l < world->numLeaves; l += 8)
@ -338,7 +344,7 @@ static u_char *world_noVisData(const world_t *world, u_char **scratchptr)
*tail++ = 0xFF;
}
*scratchptr = tail;
*buffer = tail;
return head;
}
@ -369,9 +375,9 @@ void world_draw(const world_t *world)
cam_leaf = world_leafAtPoint(world, &cam_pos);
u_char *scratchptr = scratchpad_root;
u_char *pvs = world_loadVisData(world, cam_leaf, &scratchptr);
//u_char *pvs = world_noVisData(world, &scratchptr);
u_char *pvsbuf = scratchpad;
u_char *pvs = world_loadVisData(world, cam_leaf, &pvsbuf);
//u_char *pvs = world_noVisData(world, &pvsbuf);
world_drawnode(world, 0, pvs, scratchptr);
world_drawnode(world, 0, pvs);
}
Loading…
Cancel
Save