mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-24 16:22:41 +02:00
232 lines
4.9 KiB
C
232 lines
4.9 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "platform.h"
|
|
#include "types.h"
|
|
#include "constants.h"
|
|
#include "data.h"
|
|
#include "bss.h"
|
|
#include "config.h"
|
|
#include "video.h"
|
|
#include "input.h"
|
|
#include "console.h"
|
|
#include "system.h"
|
|
#include "utils.h"
|
|
#include "net/net.h"
|
|
#include "game/hudmsg.h"
|
|
#include "game/game_1531a0.h"
|
|
#include "lib/vi.h"
|
|
|
|
#define CON_ROWS 80
|
|
#define CON_COLS 56
|
|
#define CON_VISROWS 10
|
|
#define CON_MSGROWS 4
|
|
#define CON_MSGTIMER 3.f
|
|
|
|
static char conBuf[CON_ROWS][CON_COLS + 1];
|
|
static char conInput[CON_COLS + 1];
|
|
static char *conVisRows[CON_VISROWS];
|
|
static s32 conPrintRow = 0;
|
|
static s32 conPrintCol = 0;
|
|
static s32 conMsgRows = 0;
|
|
static f32 conMsgTimer = 0.f;
|
|
static s32 conInputCol = 0;
|
|
static u32 conTextColour = 0x00ff00ff;
|
|
static s32 conOpen = 0;
|
|
static s32 conButton = 0;
|
|
|
|
void conInit(void)
|
|
{
|
|
memset(conBuf, 0, sizeof(conBuf));
|
|
memset(conInput, 0, sizeof(conInput));
|
|
memset(conVisRows, 0, sizeof(conVisRows));
|
|
conPrintRow = conPrintCol = 0;
|
|
conOpen = 0;
|
|
conMsgRows = 0;
|
|
conMsgTimer = 0.0f;
|
|
conInputCol = 0;
|
|
}
|
|
|
|
void conPrint(s32 showmsg, const char *str)
|
|
{
|
|
if (!str || !*str) {
|
|
return;
|
|
}
|
|
|
|
const s32 oldRow = conPrintRow;
|
|
|
|
for (const char *s = str; *s; ++s) {
|
|
char ch = *s;
|
|
switch (ch) {
|
|
case '\n':
|
|
if (conPrintCol) {
|
|
conPrintCol = 0;
|
|
conPrintRow = (conPrintRow + 1) % CON_ROWS;
|
|
}
|
|
break;
|
|
case '\r':
|
|
break;
|
|
case '\t':
|
|
ch = ' ';
|
|
/* fallthrough */
|
|
default:
|
|
conBuf[conPrintRow][conPrintCol++] = ch;
|
|
if (conPrintCol == CON_COLS) {
|
|
conPrintCol = 0;
|
|
conPrintRow = (conPrintRow + 1) % CON_ROWS;
|
|
}
|
|
break;
|
|
}
|
|
conBuf[conPrintRow][conPrintCol] = '\0';
|
|
}
|
|
|
|
if (conPrintRow != oldRow) {
|
|
// scroll time
|
|
for (s32 i = 0; i < ARRAYCOUNT(conVisRows); ++i) {
|
|
s32 row = conPrintRow - i - 1;
|
|
if (row < 0) {
|
|
row = CON_ROWS + row;
|
|
}
|
|
conVisRows[i] = &conBuf[row][0];
|
|
}
|
|
if (showmsg) {
|
|
if (conMsgRows < CON_MSGROWS) {
|
|
if (conPrintRow > oldRow) {
|
|
conMsgRows += conPrintRow - oldRow;
|
|
} else {
|
|
conMsgRows += conPrintRow + (CON_ROWS - oldRow);
|
|
}
|
|
}
|
|
conMsgTimer = sysGetSeconds() + CON_MSGTIMER;
|
|
}
|
|
}
|
|
}
|
|
|
|
void conPrintLn(s32 showmsg, const char *s)
|
|
{
|
|
char tmp[4096];
|
|
snprintf(tmp, sizeof(tmp), "%s\n", s);
|
|
conPrint(showmsg, tmp);
|
|
}
|
|
|
|
void conPrintf(s32 showmsg, const char *fmt, ...)
|
|
{
|
|
char tmp[4096];
|
|
tmp[sizeof(tmp) - 1] = '\0';
|
|
tmp[0] = '\0';
|
|
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vsnprintf(tmp, sizeof(tmp), fmt, args);
|
|
va_end(args);
|
|
|
|
conPrint(showmsg, tmp);
|
|
}
|
|
|
|
static inline Gfx *conRenderMsgs(Gfx *gdl)
|
|
{
|
|
if (conMsgRows) {
|
|
s32 x, y;
|
|
const u32 c = (conTextColour & 0xffffff00) | 0xa0;
|
|
for (s32 i = 0; i < conMsgRows; ++i) {
|
|
char *s = conVisRows[i];
|
|
if (s) {
|
|
x = 4;
|
|
y = 4 + 8 * (conMsgRows - i - 1);
|
|
gdl = textRenderProjected(gdl, &x, &y, s, g_CharsHandelGothicXs, g_FontHandelGothicXs, c, viGetWidth(), viGetHeight(), 0, 0);
|
|
}
|
|
}
|
|
const f32 t = sysGetSeconds();
|
|
if (conMsgTimer <= t) {
|
|
conMsgTimer = t + CON_MSGTIMER;
|
|
--conMsgRows;
|
|
}
|
|
} else {
|
|
conMsgTimer = 0;
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *conRender(Gfx *gdl)
|
|
{
|
|
if (!g_CharsHandelGothicXs || !g_FontHandelGothicXs) {
|
|
return gdl;
|
|
}
|
|
|
|
gdl = text0f153628(gdl);
|
|
|
|
if (!conOpen) {
|
|
gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, G_ASPECT_LEFT_EXT);
|
|
gdl = conRenderMsgs(gdl);
|
|
} else {
|
|
s32 x, y;
|
|
gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, G_ASPECT_CENTER_EXT);
|
|
gdl = hudmsgRenderBox(gdl, 16, 0, SCREEN_WIDTH_LO - 16, 4 + 8 * (CON_VISROWS + 1), 1.f, conTextColour, 0.9f);
|
|
for (s32 i = 0; i < CON_VISROWS; ++i) {
|
|
char *s = conVisRows[i];
|
|
if (s) {
|
|
x = 18;
|
|
y = 4 + 8 * (CON_VISROWS - i - 1);
|
|
gdl = textRenderProjected(gdl, &x, &y, s, g_CharsHandelGothicXs, g_FontHandelGothicXs, conTextColour, viGetWidth(), viGetHeight(), 0, 0);
|
|
}
|
|
}
|
|
char tmp[CON_COLS + 3];
|
|
snprintf(tmp, sizeof(tmp), "> %s", conInput);
|
|
x = 18;
|
|
y = 4 + 8 * CON_VISROWS;
|
|
gdl = textRenderProjected(gdl, &x, &y, tmp, g_CharsHandelGothicXs, g_FontHandelGothicXs, conTextColour, viGetWidth(), viGetHeight(), 0, 0);
|
|
}
|
|
|
|
gSPClearExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT);
|
|
|
|
gdl = text0f153780(gdl);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
void conTick(void)
|
|
{
|
|
const s32 button = inputKeyPressed(VK_GRAVE);
|
|
if (button && !conButton) {
|
|
conOpen = !conOpen;
|
|
if (conOpen) {
|
|
inputStartTextInput();
|
|
} else {
|
|
inputStopTextInput();
|
|
}
|
|
}
|
|
|
|
conButton = button;
|
|
|
|
if (conOpen) {
|
|
char chr = inputGetLastTextChar();
|
|
if (chr && isprint(chr)) {
|
|
if (conInputCol < CON_COLS) {
|
|
conInput[conInputCol++] = chr;
|
|
conInput[conInputCol] = '\0';
|
|
}
|
|
}
|
|
const s32 key = inputGetLastKey();
|
|
if (key == VK_BACKSPACE) {
|
|
if (conInputCol) {
|
|
conInput[--conInputCol] = '\0';
|
|
} else {
|
|
conInput[0] = '\0';
|
|
}
|
|
} else if (key == VK_RETURN) {
|
|
if (conInput[0] && conInputCol) {
|
|
if (g_NetMode) {
|
|
netChat(NULL, conInput);
|
|
}
|
|
}
|
|
conInput[0] = '\0';
|
|
conInputCol = 0;
|
|
}
|
|
inputClearLastTextChar();
|
|
inputClearLastKey();
|
|
}
|
|
}
|