PS1: Onscreen keyboard texture works

This commit is contained in:
UnknownShadow200 2025-03-15 19:43:58 +11:00
parent 587dfd1eea
commit 400c3b568d
9 changed files with 90 additions and 76 deletions

View File

@ -2,6 +2,12 @@
// and so takes less cycles to access // and so takes less cycles to access
#define SCRATCHPAD_MEM ((cc_uint8*)0x1F800000) #define SCRATCHPAD_MEM ((cc_uint8*)0x1F800000)
// === GTE COMMANDS ===
#define GTE_SetTransX(value) __asm__ volatile("ctc2 %0, $5;" :: "r" (value) : )
#define GTE_SetTransY(value) __asm__ volatile("ctc2 %0, $6;" :: "r" (value) : )
#define GTE_SetTransZ(value) __asm__ volatile("ctc2 %0, $7;" :: "r" (value) : );
// === DMA REGISTERS ===
enum dma_chrc_flags { enum dma_chrc_flags {
CHRC_STATUS_BUSY = (1 << 24), CHRC_STATUS_BUSY = (1 << 24),
}; };
@ -15,12 +21,14 @@ enum dma_chrc_CMD {
CHRC_NO_DREQ_WAIT = (1 << 28), CHRC_NO_DREQ_WAIT = (1 << 28),
}; };
// === GPU REGISTERS ===
enum gpu_status_flags { enum gpu_status_flags {
GPU_STATUS_CMD_READY = (1 << 26), GPU_STATUS_CMD_READY = (1 << 26),
GPU_STATUS_DMA_RECV_READY = (1 << 28), GPU_STATUS_DMA_RECV_READY = (1 << 28),
}; };
// === GP0 COMMANDS ===
enum gp0_cmd_type { enum gp0_cmd_type {
GP0_CMD_CLEAR_VRAM_CACHE = 0x01000000, GP0_CMD_CLEAR_VRAM_CACHE = 0x01000000,
GP0_CMD_MEM_FILL = 0x02000000, GP0_CMD_MEM_FILL = 0x02000000,
@ -44,6 +52,20 @@ enum gp0_rectcmd_flags {
RECT_CMD_1x1 = 1u << 27, RECT_CMD_1x1 = 1u << 27,
}; };
#define PACK_RGBC(r, g, b, c) ( (r) | ((g) << 8) | ((b) << 16) | (c) )
#define GP0_CMD_DRAW_MIN_PACK(x, y) ( GP0_CMD_DRAW_AREA_MIN | ((x) & 0x3FF) | (((y) & 0x3FF) << 10) )
#define GP0_CMD_DRAW_MAX_PACK(x, y) ( GP0_CMD_DRAW_AREA_MAX | ((x) & 0x3FF) | (((y) & 0x3FF) << 10) )
#define GP0_CMD_DRAW_OFFSET_PACK(x, y) ( GP0_CMD_DRAW_AREA_OFFSET | ((x) & 0x7FF) | (((y) & 0x7FF) << 11) )
#define GP0_CMD_FILL_XY(x, y) ( ((x) & 0xFFFF) | (((y) & 0xFFFF) << 16) )
#define GP0_CMD_FILL_WH(w, h) ( ((w) & 0xFFFF) | (((h) & 0xFFFF) << 16) )
#define GP0_CMD_CLUT_XY(x, y) ( ((x) & 0x3F) | (((y) & 0x1FF) << 6) )
// === GP1 COMMANDS ===
enum gp1_cmd_type { enum gp1_cmd_type {
GP1_CMD_RESET_GPU = 0x00000000, GP1_CMD_RESET_GPU = 0x00000000,
GP1_CMD_DISPLAY_ACTIVE = 0x03000000, GP1_CMD_DISPLAY_ACTIVE = 0x03000000,
@ -69,24 +91,10 @@ enum gp1_cmd_display_mode {
GP1_VER_RES_240 = 0 << 2, GP1_VER_RES_240 = 0 << 2,
}; };
// === MISC COMMANDS ===
#define GP0_CMD_DRAW_MIN_PACK(x, y) ( GP0_CMD_DRAW_AREA_MIN | ((x) & 0x3FF) | (((y) & 0x3FF) << 10) )
#define GP0_CMD_DRAW_MAX_PACK(x, y) ( GP0_CMD_DRAW_AREA_MAX | ((x) & 0x3FF) | (((y) & 0x3FF) << 10) )
#define GP0_CMD_DRAW_OFFSET_PACK(x, y) ( GP0_CMD_DRAW_AREA_OFFSET | ((x) & 0x7FF) | (((y) & 0x7FF) << 11) )
#define GP1_CMD_DISPLAY_ADDRESS_XY(x, y) ( ((x) & 0x3FF) | (((y) & 0x1FF) << 10) ) #define GP1_CMD_DISPLAY_ADDRESS_XY(x, y) ( ((x) & 0x3FF) | (((y) & 0x1FF) << 10) )
#define GP0_CMD_FILL_XY(x, y) ( ((x) & 0xFFFF) | (((y) & 0xFFFF) << 16) )
#define GP0_CMD_FILL_WH(w, h) ( ((w) & 0xFFFF) | (((h) & 0xFFFF) << 16) )
#define PACK_RGBC(r, g, b, c) ( (r) | ((g) << 8) | ((b) << 16) | (c) ) // === GP0 POLYGON COMMANDS ===
#define GP0_CMD_CLUT_XY(x, y) ( ((x) & 0x3F) | (((y) & 0x1FF) << 6) )
// === POLYGON COMMANDS ===
#define POLY_CODE_F4 (GP0_CMD_POLYGON | POLY_CMD_QUAD) #define POLY_CODE_F4 (GP0_CMD_POLYGON | POLY_CMD_QUAD)
#define POLY_LEN_F4 5 #define POLY_LEN_F4 5
struct PSX_POLY_F4 { struct PSX_POLY_F4 {

View File

@ -515,7 +515,7 @@ int Entities_GetClosest(struct Entity* src) {
if (!e || e == &Entities.CurPlayer->Base) continue; if (!e || e == &Entities.CurPlayer->Base) continue;
if (!Intersection_RayIntersectsRotatedBox(eyePos, dir, e, &t0, &t1)) continue; if (!Intersection_RayIntersectsRotatedBox(eyePos, dir, e, &t0, &t1)) continue;
if (targetID == -1 || t0 < closestDist) { if (targetID < 0 || t0 < closestDist) {
closestDist = t0; closestDist = t0;
targetID = i; targetID = i;
} }

View File

@ -347,9 +347,14 @@ USAGE NOTES:
is setup to draw groups of 2 triangles from 4 vertices (1 quad) is setup to draw groups of 2 triangles from 4 vertices (1 quad)
*/ */
/* Optional draw hints used by some rendering backends to speed up 2D drawing */
typedef enum DrawHints_ { typedef enum DrawHints_ {
DRAW_HINT_NONE = 0, DRAW_HINT_NONE = 0,
DRAW_HINT_SPRITE = 9, /* Vertices are 2D rects with possible texture scaling and/or repeating */
DRAW_HINT_SPRITE = 0x02,
/* Vertices are 2D rects with no texture scaling or repeating */
/* Typically this is only used for textures purely containing text */
DRAW_HINT_RECT = 0x04,
} DrawHints; } DrawHints;
/* Sets the format of the rendered vertices */ /* Sets the format of the rendered vertices */

View File

@ -249,42 +249,23 @@ void Gfx_TransferToVRAM(int x, int y, int w, int h, void* pixels) {
// 10 texture pages are occupied by the doublebuffered display // 10 texture pages are occupied by the doublebuffered display
// 22 texture pages are usable for textures // 22 texture pages are usable for textures
// These 22 pages are then divided into: // These 22 pages are then divided into:
// - 5 for 128+ wide horizontal, 6 otherwise // - 4,4,3 pages for horizontal textures
// - 11 pages for vertical textures // - 4,4,3 pages for vertical textures
#define TPAGE_WIDTH 64 #define TPAGE_WIDTH 64
#define TPAGE_HEIGHT 256 #define TPAGE_HEIGHT 256
#define TPAGES_PER_HALF 16 #define TPAGES_PER_HALF 16
// Horizontally oriented textures (first group of 16) #define MAX_TEX_GROUPS 3
#define TPAGE_START_HOR 5 #define TEX_GROUP_LINES 256
#define MAX_HOR_TEX_PAGES 11 #define MAX_TEX_LINES (MAX_TEX_GROUPS * TEX_GROUP_LINES)
#define MAX_HOR_TEX_LINES (MAX_HOR_TEX_PAGES * TPAGE_HEIGHT)
// Horizontally oriented textures (second group of 16) static cc_uint8 vram_used[(MAX_TEX_LINES + MAX_TEX_LINES) / 8];
#define TPAGE_START_VER (16 + 5)
#define MAX_VER_TEX_PAGES 11
#define MAX_VER_TEX_LINES (MAX_VER_TEX_PAGES * TPAGE_WIDTH)
static cc_uint8 vram_used[(MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES) / 8];
#define VRAM_SetUsed(line) (vram_used[(line) / 8] |= (1 << ((line) % 8))) #define VRAM_SetUsed(line) (vram_used[(line) / 8] |= (1 << ((line) % 8)))
#define VRAM_UnUsed(line) (vram_used[(line) / 8] &= ~(1 << ((line) % 8))) #define VRAM_UnUsed(line) (vram_used[(line) / 8] &= ~(1 << ((line) % 8)))
#define VRAM_IsUsed(line) (vram_used[(line) / 8] & (1 << ((line) % 8))) #define VRAM_IsUsed(line) (vram_used[(line) / 8] & (1 << ((line) % 8)))
#define VRAM_BoundingAxis(width, height) height > width ? width : height #define VRAM_BoundingAxis(width, height) height > width ? width : height
static void VRAM_GetBlockRange(int width, int height, int* beg, int* end) {
if (height > width) {
*beg = MAX_HOR_TEX_LINES;
*end = MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES;
} else if (width >= 128) {
*beg = 0;
*end = 5 * TPAGE_HEIGHT;
} else {
*beg = 5 * TPAGE_HEIGHT;
*end = MAX_HOR_TEX_LINES;
}
}
static cc_bool VRAM_IsRangeFree(int beg, int end) { static cc_bool VRAM_IsRangeFree(int beg, int end) {
for (int i = beg; i < end; i++) for (int i = beg; i < end; i++)
{ {
@ -293,16 +274,33 @@ static cc_bool VRAM_IsRangeFree(int beg, int end) {
return true; return true;
} }
static int VRAM_FindFreeBlock(int width, int height) { static int VRAM_FindFreeLines(int group, int lines) {
int beg, end; int beg = group * TEX_GROUP_LINES;
VRAM_GetBlockRange(width, height, &beg, &end); int end = beg + TEX_GROUP_LINES;
// TODO kinda inefficient // TODO kinda inefficient
for (int i = beg; i < end - height; i++) for (int i = beg; i < end - lines; i++)
{ {
if (VRAM_IsUsed(i)) continue; if (VRAM_IsUsed(i)) continue;
if (VRAM_IsRangeFree(i, i + height)) return i; if (VRAM_IsRangeFree(i, i + lines)) return i;
}
return -1;
}
static int VRAM_FindFreeBlock(int width, int height) {
int l;
if (height > width) {
// Vertically oriented texture
if ((l = VRAM_FindFreeLines(3, width)) >= 0) return l;
if ((l = VRAM_FindFreeLines(4, width)) >= 0) return l;
if ((l = VRAM_FindFreeLines(5, width)) >= 0) return l;
} else {
// Horizontally oriented texture
if ((l = VRAM_FindFreeLines(0, height)) >= 0) return l;
if ((l = VRAM_FindFreeLines(1, height)) >= 0) return l;
if ((l = VRAM_FindFreeLines(2, height)) >= 0) return l;
} }
return -1; return -1;
} }
@ -323,11 +321,15 @@ static void VRAM_FreeBlock(int line, int width, int height) {
} }
} }
#define TPAGE_START_HOR 5
#define TPAGE_START_VER 21
static int VRAM_CalcPage(int line) { static int VRAM_CalcPage(int line) {
if (line < MAX_HOR_TEX_LINES) { if (line < TEX_GROUP_LINES * MAX_TEX_GROUPS) {
return TPAGE_START_HOR + (line / TPAGE_HEIGHT); int group = line / TPAGE_HEIGHT;
return TPAGE_START_HOR + (group * 4);
} else { } else {
line -= MAX_HOR_TEX_LINES; line -= TEX_GROUP_LINES * MAX_TEX_GROUPS;
return TPAGE_START_VER + (line / TPAGE_WIDTH); return TPAGE_START_VER + (line / TPAGE_WIDTH);
} }
} }
@ -713,17 +715,17 @@ void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); }
*---------------------------------------------------------Matrices--------------------------------------------------------* *---------------------------------------------------------Matrices--------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static struct Matrix _view, _proj; static struct Matrix _view, _proj;
static MATRIX transform_matrix;
#define ToFixed(v) (int)(v * (1 << 12)) #define ToFixed(v) (int)(v * (1 << 12))
#define ToFixedTr(v) (int)(v * (1 << 8)) #define ToFixedTr(v) (int)(v * (1 << 8))
static void LoadTransformMatrix(struct Matrix* src) { static void LoadTransformMatrix(struct Matrix* src) {
MATRIX transform_matrix;
// Use w instead of z // Use w instead of z
// (row123.z = row123.w, only difference is row4.z/w being different) // (row123.z = row123.w, only difference is row4.z/w being different)
transform_matrix.t[0] = ToFixedTr(src->row4.x); GTE_SetTransX(ToFixedTr( src->row4.x));
transform_matrix.t[1] = ToFixedTr(-src->row4.y); GTE_SetTransY(ToFixedTr(-src->row4.y));
transform_matrix.t[2] = ToFixedTr(src->row4.w); GTE_SetTransZ(ToFixedTr( src->row4.w));
transform_matrix.m[0][0] = ToFixed(src->row1.x); transform_matrix.m[0][0] = ToFixed(src->row1.x);
@ -739,7 +741,6 @@ static void LoadTransformMatrix(struct Matrix* src) {
transform_matrix.m[2][2] = ToFixed(src->row3.w); transform_matrix.m[2][2] = ToFixed(src->row3.w);
gte_SetRotMatrix(&transform_matrix); gte_SetRotMatrix(&transform_matrix);
gte_SetTransMatrix(&transform_matrix);
} }
void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {

View File

@ -384,7 +384,7 @@ static CC_INLINE int FastFloor(float value) {
return valueI > value ? valueI - 1 : valueI; return valueI > value ? valueI - 1 : valueI;
} }
static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2) { static void DrawSprite2D(Vertex* V0, Vertex* V1, Vertex* V2, int hints) {
PackedCol vColor = V0->c; PackedCol vColor = V0->c;
int minX = (int)V0->x; int minX = (int)V0->x;
int minY = (int)V0->y; int minY = (int)V0->y;
@ -961,7 +961,7 @@ void DrawQuads(int startVertex, int verticesCount, DrawHints hints) {
Vertex vertices[4]; Vertex vertices[4];
int j = startVertex; int j = startVertex;
if (gfx_rendering2D && hints == DRAW_HINT_SPRITE) { if (gfx_rendering2D && (hints & (DRAW_HINT_SPRITE|DRAW_HINT_RECT))) {
// 4 vertices = 1 quad = 2 triangles // 4 vertices = 1 quad = 2 triangles
for (int i = 0; i < verticesCount / 4; i++, j += 4) for (int i = 0; i < verticesCount / 4; i++, j += 4)
{ {

View File

@ -2632,7 +2632,7 @@ static void TexIdsOverlay_Render(void* screen, float delta) {
offset = TexIdsOverlay_RenderTerrain(s, offset); offset = TexIdsOverlay_RenderTerrain(s, offset);
Gfx_BindTexture(s->idAtlas.tex.ID); Gfx_BindTexture(s->idAtlas.tex.ID);
Gfx_DrawVb_IndexedTris_Range(s->textVertices, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(s->textVertices, offset, DRAW_HINT_RECT);
} }
static int TexIdsOverlay_KeyDown(void* screen, int key, struct InputDevice* device) { static int TexIdsOverlay_KeyDown(void* screen, int key, struct InputDevice* device) {

View File

@ -400,7 +400,7 @@ static void HUDScreen_Render(void* screen, float delta) {
} else if (IsOnlyChatActive() && Gui.ShowFPS) { } else if (IsOnlyChatActive() && Gui.ShowFPS) {
Widget_Render2(&s->line2, 8); Widget_Render2(&s->line2, 8);
Gfx_BindTexture(s->posAtlas.tex.ID); Gfx_BindTexture(s->posAtlas.tex.ID);
Gfx_DrawVb_IndexedTris_Range(s->posCount, 12 + HOTBAR_MAX_VERTICES, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(s->posCount, 12 + HOTBAR_MAX_VERTICES, DRAW_HINT_RECT);
/* TODO swap these two lines back */ /* TODO swap these two lines back */
} }
@ -845,7 +845,7 @@ static void TabListOverlay_Render(void* screen, float delta) {
if (!s->textures[i].ID) continue; if (!s->textures[i].ID) continue;
Gfx_BindTexture(s->textures[i].ID); Gfx_BindTexture(s->textures[i].ID);
Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_RECT);
offset += 4; offset += 4;
} }
@ -1176,7 +1176,7 @@ static void ChatScreen_DrawChat(struct ChatScreen* s, float delta) {
if (Chat_GetLogTime(logIdx) + 10 < now) continue; if (Chat_GetLogTime(logIdx) + 10 < now) continue;
Gfx_BindTexture(texID); Gfx_BindTexture(texID);
Gfx_DrawVb_IndexedTris_Range(4, i * 4, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, i * 4, DRAW_HINT_RECT);
} }
} }
@ -1949,7 +1949,7 @@ static void LoadingScreen_Render(void* screen, float delta) {
if (s->rows) { if (s->rows) {
loc = Block_Tex(BLOCK_DIRT, FACE_YMAX); loc = Block_Tex(BLOCK_DIRT, FACE_YMAX);
Atlas1D_Bind(Atlas1D_Index(loc)); Atlas1D_Bind(Atlas1D_Index(loc));
Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(s->rows * 4, 0, 0);
offset = s->rows * 4; offset = s->rows * 4;
} }

View File

@ -241,7 +241,7 @@ static double net_lastPacket;
static cc_uint8 lastOpcode; static cc_uint8 lastOpcode;
static cc_bool net_connecting; static cc_bool net_connecting;
static double net_connectTimeout; static float net_connectElapsed;
#define NET_TIMEOUT_SECS 15 #define NET_TIMEOUT_SECS 15
static void MPConnection_FinishConnect(void) { static void MPConnection_FinishConnect(void) {
@ -276,20 +276,20 @@ static void MPConnection_FailConnect(cc_result result) {
MPConnection_Fail(&reason); MPConnection_Fail(&reason);
} }
static void MPConnection_TickConnect(void) { static void MPConnection_TickConnect(struct ScheduledTask* task) {
cc_bool writable; cc_bool writable;
double now = Game.Time;
cc_result res = Socket_CheckWritable(net_socket, &writable); cc_result res = Socket_CheckWritable(net_socket, &writable);
net_connectElapsed += task->interval;
if (res) { if (res) {
MPConnection_FailConnect(res); MPConnection_FailConnect(res);
} else if (writable) { } else if (writable) {
MPConnection_FinishConnect(); MPConnection_FinishConnect();
} else if (now > net_connectTimeout) { } else if (net_connectElapsed > NET_TIMEOUT_SECS) {
MPConnection_FailConnect(0); MPConnection_FailConnect(0);
} else { } else {
double left = net_connectTimeout - now; float left = NET_TIMEOUT_SECS - net_connectElapsed;
Event_RaiseFloat(&WorldEvents.Loading, (float)left / NET_TIMEOUT_SECS); Event_RaiseFloat(&WorldEvents.Loading, left / NET_TIMEOUT_SECS);
} }
} }
@ -325,7 +325,7 @@ static void MPConnection_BeginConnect(void) {
} else { } else {
Server.Disconnected = false; Server.Disconnected = false;
net_connecting = true; net_connecting = true;
net_connectTimeout = Game.Time + NET_TIMEOUT_SECS; net_connectElapsed = 0;
String_Format2(&title, "Connecting to %s:%i..", &Server.Address, &Server.Port); String_Format2(&title, "Connecting to %s:%i..", &Server.Address, &Server.Port);
LoadingScreen_Show(&title, &String_Empty); LoadingScreen_Show(&title, &String_Empty);
@ -386,7 +386,7 @@ static void MPConnection_Tick(struct ScheduledTask* task) {
cc_result res; cc_result res;
if (Server.Disconnected) return; if (Server.Disconnected) return;
if (net_connecting) { MPConnection_TickConnect(); return; } if (net_connecting) { MPConnection_TickConnect(task); return; }
/* NOTE: using a read call that is a multiple of 4096 (appears to?) improve read performance */ /* NOTE: using a read call that is a multiple of 4096 (appears to?) improve read performance */
res = Socket_Read(net_socket, net_readCurrent, 4096 * 4, &read); res = Socket_Read(net_socket, net_readCurrent, 4096 * 4, &read);

View File

@ -61,7 +61,7 @@ static int TextWidget_Render2(void* widget, int offset) {
struct TextWidget* w = (struct TextWidget*)widget; struct TextWidget* w = (struct TextWidget*)widget;
if (w->tex.ID) { if (w->tex.ID) {
Gfx_BindTexture(w->tex.ID); Gfx_BindTexture(w->tex.ID);
Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_RECT);
} }
return offset + 4; return offset + 4;
} }
@ -1592,12 +1592,12 @@ static void TextInputWidget_BuildMesh(void* widget, struct VertexTextured** vert
static int TextInputWidget_Render2(void* widget, int offset) { static int TextInputWidget_Render2(void* widget, int offset) {
struct InputWidget* w = (struct InputWidget*)widget; struct InputWidget* w = (struct InputWidget*)widget;
Gfx_BindTexture(w->inputTex.ID); Gfx_BindTexture(w->inputTex.ID);
Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_RECT);
offset += 4; offset += 4;
if (w->showCaret && Math_Mod1((float)w->caretAccumulator) < 0.5f) { if (w->showCaret && Math_Mod1((float)w->caretAccumulator) < 0.5f) {
Gfx_BindTexture(w->caretTex.ID); Gfx_BindTexture(w->caretTex.ID);
Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_RECT);
} }
return offset + 4; return offset + 4;
} }
@ -2455,7 +2455,7 @@ static int TextGroupWidget_Render2(void* widget, int offset) {
if (!textures[i].ID) continue; if (!textures[i].ID) continue;
Gfx_BindTexture(textures[i].ID); Gfx_BindTexture(textures[i].ID);
Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_SPRITE); Gfx_DrawVb_IndexedTris_Range(4, offset, DRAW_HINT_RECT);
} }
return offset; return offset;
} }