Broken PS1 port

This commit is contained in:
UnknownShadow200 2024-03-27 16:31:01 +11:00
parent 8bfe004d71
commit eff5ddabd2
13 changed files with 871 additions and 3 deletions

4
.gitignore vendored
View file

@ -72,6 +72,10 @@ ClassiCube*
screenshots
fontscache.txt
# CMake files
CMakeFiles/
CMakeCache.txt
#GCC object files
*.o

View file

@ -138,6 +138,9 @@ vita:
$(MAKE) -f misc/vita/Makefile PLAT=vita
ps3:
$(MAKE) -f misc/ps3/Makefile PLAT=ps3
ps1:
cmake --preset default misc/ps1
cmake --build misc/ps1/build
ps2:
$(MAKE) -f misc/ps2/Makefile PLAT=ps2
xbox:

21
misc/ps1/CMakeLists.txt Normal file
View file

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.21)
project(
ClassiCube
LANGUAGES C ASM
VERSION 1.0.0
DESCRIPTION "ClassiCube PS1 port"
HOMEPAGE_URL "https://classicube.net"
)
add_definitions(-DPLAT_PS1)
file(GLOB _sources ../../src/*.c)
psn00bsdk_add_executable(template GPREL ${_sources})
psn00bsdk_add_cd_image(
iso # Target name
template # Output file name (= template.bin + template.cue)
iso.xml # Path to config file
DEPENDS template system.cnf
)

View file

@ -0,0 +1,26 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default configuration",
"description": "Use this preset to build the project using PSn00bSDK.",
"generator": "Ninja",
"toolchainFile": "$env{PSN00BSDK_LIBS}/cmake/sdk.cmake",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"PSN00BSDK_TC": "",
"PSN00BSDK_TARGET": "mipsel-none-elf"
},
"warnings": {
"dev": false
}
}
]
}

83
misc/ps1/iso.xml Normal file
View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is processed by CMake and used by mkpsxiso to build the CD image.
NOTE: all paths are relative to the build directory; if you want to include
a file from the source tree, you'll have to prepend its path with
${PROJECT_SOURCE_DIR}.
-->
<iso_project>
<track type="data">
<!--
The "volume", "volume_set", "publisher", "data_preparer" and
"copyright" strings below can be freely modified. The ISO9660
specification, however, imposes the following limitations:
- "volume" and "volume_set" must be 32 characters or less, and can
only contain uppercase letters, digits and underscores.
- "publisher" and "data_preparer" can be up to 128 characters long
and can additionally contain spaces and some special characters.
- "copyright" should be a path to a file on the disc, even one that
does not exist (but in practice it can be set to anything).
"system" and "application" must always be set to "PLAYSTATION" in
order for the disc to be recognized as valid.
-->
<identifiers
system ="PLAYSTATION"
volume ="PSN00BSDK_TEMPLATE"
volume_set ="PSN00BSDK_TEMPLATE"
publisher ="MEIDOTEK"
data_preparer ="PSN00BSDK ${PSN00BSDK_VERSION}"
application ="PLAYSTATION"
copyright ="README.TXT;1"
/>
<!--
You may optionally include a license file using the <license> tag.
Some consoles, particularly Japanese or PAL models with a modchip,
require the disc to contain valid license data and will refuse to
boot if it is missing. License files are usually not required on
US consoles or when booting via softmods or cheat cartridges.
License files are region-specific and are not distributed with
PSn00bSDK for obvious reasons, but can be dumped from an official
game using dumpsxiso or extracted from the Sony SDK.
-->
<!--<license file="${PROJECT_SOURCE_DIR}/license.dat" />-->
<!--
Files and directories can be added to the disc by placing <file>
and <dir> tags below. All file names are case-insensitive and must
be in 8.3 format, i.e. no more than 8 characters for the name and 3
for the optional extension. Directories cannot have extensions.
A boot configuration file (SYSTEM.CNF) or executable (PSX.EXE) must
be present in the root directory. Due to BIOS limitations the root
directory cannot hold more than 30 files or directories, and the
entire disc must contain 45 directories or less. Subdirectories can
contain any number of files.
-->
<directory_tree>
<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />
<file name="TEMPLATE.EXE" type="data" source="template.exe" />
<!--
This file is only required if you are using dynamic linking
(see the system/dynlink example). It contains the executable's
symbol map and can be used to obtain the address of a function
or global variable by its name.
-->
<!--<file name="TEMPLATE.MAP" type="data" source="template.map" />-->
<dummy sectors="1024"/>
</directory_tree>
</track>
<!--
CD-DA tracks can be added to the CD image by using one or more <track>
tags. The source attribute must be a path to an audio file in WAV, FLAC
or MP3 format (using WAV or FLAC is highly recommended to preserve
audio quality if you have a lossless copy of the source track).
-->
<!--<track type="audio" source="${PROJECT_SOURCE_DIR}/track2.wav" />-->
</iso_project>

4
misc/ps1/system.cnf Normal file
View file

@ -0,0 +1,4 @@
BOOT=cdrom:\template.exe;1
TCB=4
EVENT=10
STACK=801FFFF0

View file

@ -368,6 +368,14 @@ typedef cc_uint8 cc_bool;
#define CC_BUILD_GLES
#define CC_BUILD_EGL
#undef CC_BUILD_FREETYPE
#elif defined PLAT_PS1
#define CC_BUILD_PS1
#define CC_BUILD_OPENAL
#define CC_BUILD_HTTPCLIENT
#define CC_BUILD_COOPTHREADED
#define CC_BUILD_LOWMEM
#define CC_BUILD_CONSOLE
#undef CC_BUILD_FREETYPE
#endif
#endif

View file

@ -4,8 +4,15 @@
/* For abs(x) function */
#include <stdlib.h>
#ifndef __GNUC__
#if defined PLAT_PS1
float Math_AbsF(float x) { return __builtin_fabsf(x); }
float Math_SqrtF(float x) { return 0; } /* TODO broken */
#elif defined __GNUC__
/* Defined in .h using builtins */
#else
#include <math.h>
float Math_AbsF(float x) { return fabsf(x); /* MSVC intrinsic */ }
float Math_SqrtF(float x) { return sqrtf(x); /* MSVC intrinsic */ }
#endif

View file

@ -14,7 +14,7 @@
#define Math_Deg2Packed(x) ((cc_uint8)((x) * 256.0f / 360.0f))
#define Math_Packed2Deg(x) ((x) * 360.0f / 256.0f)
#ifdef __GNUC__
#if defined __GNUC__ && !defined CC_PLAT_PS1
/* fabsf/sqrtf are single intrinsic instructions in gcc/clang */
/* (sqrtf is only when -fno-math-errno though) */
#define Math_AbsF(x) __builtin_fabsf(x)

272
src/Graphics_PS1.c Normal file
View file

@ -0,0 +1,272 @@
#include "Core.h"
#if defined CC_BUILD_PS1
#include "_GraphicsBase.h"
#include "Errors.h"
#include "Window.h"
void Gfx_RestoreState(void) {
InitDefaultResources();
}
void Gfx_FreeState(void) {
FreeDefaultResources();
}
void Gfx_Create(void) {
Gfx.MaxTexWidth = 128;
Gfx.MaxTexHeight = 128;
Gfx.Created = true;
Gfx_RestoreState();
}
void Gfx_Free(void) {
Gfx_FreeState();
}
/*########################################################################################################################*
*---------------------------------------------------------Textures--------------------------------------------------------*
*#########################################################################################################################*/
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
return NULL;
}
void Gfx_BindTexture(GfxResourceID texId) {
}
void Gfx_DeleteTexture(GfxResourceID* texId) {
GfxResourceID data = *texId;
if (data) Mem_Free(data);
*texId = NULL;
}
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
// TODO
}
void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps) {
// TODO
}
void Gfx_EnableMipmaps(void) { }
void Gfx_DisableMipmaps(void) { }
/*########################################################################################################################*
*------------------------------------------------------State management---------------------------------------------------*
*#########################################################################################################################*/
void Gfx_SetFog(cc_bool enabled) { }
void Gfx_SetFogCol(PackedCol col) { }
void Gfx_SetFogDensity(float value) { }
void Gfx_SetFogEnd(float value) { }
void Gfx_SetFogMode(FogFunc func) { }
void Gfx_SetFaceCulling(cc_bool enabled) {
// TODO
}
void Gfx_SetAlphaTest(cc_bool enabled) {
}
void Gfx_SetAlphaBlending(cc_bool enabled) {
}
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
void Gfx_ClearBuffers(GfxBuffers buffers) {
}
void Gfx_ClearColor(PackedCol color) {
}
void Gfx_SetDepthTest(cc_bool enabled) {
}
void Gfx_SetDepthWrite(cc_bool enabled) {
// TODO
}
static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
// TODO
}
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {
cc_bool enabled = !depthOnly;
SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1],
enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]);
}
/*########################################################################################################################*
*-------------------------------------------------------Index buffers-----------------------------------------------------*
*#########################################################################################################################*/
GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) {
return (void*)1;
}
void Gfx_BindIb(GfxResourceID ib) { }
void Gfx_DeleteIb(GfxResourceID* ib) { }
/*########################################################################################################################*
*-------------------------------------------------------Vertex buffers----------------------------------------------------*
*#########################################################################################################################*/
static void* gfx_vertices;
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
return Mem_TryAlloc(count, strideSizes[fmt]);
}
void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; }
void Gfx_DeleteVb(GfxResourceID* vb) {
GfxResourceID data = *vb;
if (data) Mem_Free(data);
*vb = 0;
}
void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
return vb;
}
void Gfx_UnlockVb(GfxResourceID vb) {
gfx_vertices = vb;
}
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return Mem_TryAlloc(maxVertices, strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
return vb;
}
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
gfx_vertices = vb;
}
void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); }
/*########################################################################################################################*
*---------------------------------------------------------Matrices--------------------------------------------------------*
*#########################################################################################################################*/
static struct Matrix _view, _proj, mvp;
void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {
if (type == MATRIX_VIEW) _view = *matrix;
if (type == MATRIX_PROJECTION) _proj = *matrix;
Matrix_Mul(&mvp, &_view, &_proj);
// TODO
}
void Gfx_LoadIdentityMatrix(MatrixType type) {
Gfx_LoadMatrix(type, &Matrix_Identity);
// TODO
}
void Gfx_EnableTextureOffset(float x, float y) {
// TODO
}
void Gfx_DisableTextureOffset(void) {
// TODO
}
void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) {
/* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glortho */
/* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */
*matrix = Matrix_Identity;
matrix->row1.x = 2.0f / width;
matrix->row2.y = -2.0f / height;
matrix->row3.z = -2.0f / (zFar - zNear);
matrix->row4.x = -1.0f;
matrix->row4.y = 1.0f;
matrix->row4.z = -(zFar + zNear) / (zFar - zNear);
}
static double Cotangent(double x) { return Math_Cos(x) / Math_Sin(x); }
void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) {
float zNear_ = zFar;
float zFar_ = 0.1f;
float c = (float)Cotangent(0.5f * fov);
/* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glfrustum */
/* For pos FOV based perspective matrix, left/right/top/bottom are calculated as: */
/* left = -c * aspect, right = c * aspect, bottom = -c, top = c */
/* Calculations are simplified because of left/right and top/bottom symmetry */
*matrix = Matrix_Identity;
// TODO: Check is Frustum culling needs changing for this
matrix->row1.x = c / aspect;
matrix->row2.y = c;
matrix->row3.z = -(zFar_ + zNear_) / (zFar_ - zNear_);
matrix->row3.w = -1.0f;
matrix->row4.z = -(2.0f * zFar_ * zNear_) / (zFar_ - zNear_);
matrix->row4.w = 0.0f;
}
/*########################################################################################################################*
*---------------------------------------------------------Rendering-------------------------------------------------------*
*#########################################################################################################################*/
void Gfx_SetVertexFormat(VertexFormat fmt) {
gfx_format = fmt;
gfx_stride = strideSizes[fmt];
}
void Gfx_DrawVb_Lines(int verticesCount) {
}
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
}
void Gfx_DrawVb_IndexedTris(int verticesCount) {
}
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
}
/*########################################################################################################################*
*---------------------------------------------------------Other/Misc------------------------------------------------------*
*#########################################################################################################################*/
cc_result Gfx_TakeScreenshot(struct Stream* output) {
return ERR_NOT_SUPPORTED;
}
cc_bool Gfx_WarnIfNecessary(void) {
return false;
}
void Gfx_BeginFrame(void) {
}
void Gfx_EndFrame(void) {
if (gfx_minFrameMs) LimitFPS();
}
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
gfx_minFrameMs = minFrameMs;
gfx_vsync = vsync;
}
void Gfx_OnWindowResize(void) {
// TODO
}
void Gfx_GetApiInfo(cc_string* info) {
String_AppendConst(info, "-- Using PS1 --\n");
PrintMaxTextureInfo(info);
}
cc_bool Gfx_TryRestoreContext(void) { return true; }
#endif

229
src/Platform_PS1.c Normal file
View file

@ -0,0 +1,229 @@
#include "Core.h"
#if defined PLAT_PS1
#include "_PlatformBase.h"
#include "Stream.h"
#include "ExtMath.h"
#include "Funcs.h"
#include "Window.h"
#include "Utils.h"
#include "Errors.h"
#include "PackedCol.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <psxetc.h>
#include <psxapi.h>
#include <psxpad.h>
#include <hwregs_c.h>
#include "_PlatformConsole.h"
const cc_result ReturnCode_FileShareViolation = 1000000000; // not used
const cc_result ReturnCode_FileNotFound = 99999;
const cc_result ReturnCode_DirectoryExists = 99999;
const cc_result ReturnCode_SocketInProgess = -1;
const cc_result ReturnCode_SocketWouldBlock = -1;
const char* Platform_AppNameSuffix = " PS1";
void exit(int code) { } // TODO how to fix
/*########################################################################################################################*
*------------------------------------------------------Logging/Time-------------------------------------------------------*
*#########################################################################################################################*/
void Platform_Log(const char* msg, int len) {
char tmp[2048 + 1];
len = min(len, 2048);
Mem_Copy(tmp, msg, len); tmp[len] = '\0';
printf("%s\n", tmp);
}
#define UnixTime_TotalMS(time) ((cc_uint64)time.tv_sec * 1000 + UNIX_EPOCH + (time.tv_usec / 1000))
TimeMS DateTime_CurrentUTC_MS(void) {
return 0;
}
void DateTime_CurrentLocal(struct DateTime* t) {
Mem_Set(t, 0, sizeof(struct DateTime));
}
/*########################################################################################################################*
*--------------------------------------------------------Stopwatch--------------------------------------------------------*
*#########################################################################################################################*/
static volatile cc_uint32 irq_count;
cc_uint64 Stopwatch_Measure(void) {
return irq_count;
}
cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
if (end < beg) return 0;
return (end - beg); // TODO calculate ???
}
static void timer2_handler(void) {
irq_count++;
}
static void Stopwatch_Init(void) {
TIMER_CTRL(2) = 0x0260; // CLK/8 input, repeated IRQ on overflow
EnterCriticalSection();
InterruptCallback(IRQ_TIMER2, &timer2_handler);
ExitCriticalSection();
}
/*########################################################################################################################*
*-----------------------------------------------------Directory/File------------------------------------------------------*
*#########################################################################################################################*/
cc_result Directory_Create(const cc_string* path) {
return ERR_NOT_SUPPORTED;
}
int File_Exists(const cc_string* path) {
return 0;
}
cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Open(cc_file* file, const cc_string* path) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Create(cc_file* file, const cc_string* path) {
return ERR_NOT_SUPPORTED;
}
cc_result File_OpenOrCreate(cc_file* file, const cc_string* path) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Close(cc_file file) {
return 0;
}
cc_result File_Seek(cc_file file, int offset, int seekType) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Position(cc_file file, cc_uint32* pos) {
return ERR_NOT_SUPPORTED;
}
cc_result File_Length(cc_file file, cc_uint32* len) {
return ERR_NOT_SUPPORTED;
}
/*########################################################################################################################*
*--------------------------------------------------------Threading--------------------------------------------------------*
*#########################################################################################################################*/
void Thread_Sleep(cc_uint32 milliseconds) {
// TODO sleep a bit
VSync(0);
}
void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) {
*handle = NULL;
}
void Thread_Detach(void* handle) {
}
void Thread_Join(void* handle) {
}
void* Mutex_Create(void) {
return NULL;
}
void Mutex_Free(void* handle) {
}
void Mutex_Lock(void* handle) {
}
void Mutex_Unlock(void* handle) {
}
void* Waitable_Create(void) {
return NULL;
}
void Waitable_Free(void* handle) {
}
void Waitable_Signal(void* handle) {
}
void Waitable_Wait(void* handle) {
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
}
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) {
return ERR_NOT_SUPPORTED;
}
cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) {
return ERR_NOT_SUPPORTED;
}
cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
return ERR_NOT_SUPPORTED;
}
cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
return ERR_NOT_SUPPORTED;
}
void Socket_Close(cc_socket s) {
}
cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) {
return ERR_NOT_SUPPORTED;
}
cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
return ERR_NOT_SUPPORTED;
}
/*########################################################################################################################*
*--------------------------------------------------------Platform---------------------------------------------------------*
*#########################################################################################################################*/
void Platform_Init(void) {
ResetGraph( 0 );
Stopwatch_Init();
}
void Platform_Free(void) { }
cc_bool Platform_DescribeError(cc_result res, cc_string* dst) {
return false;
}
/*########################################################################################################################*
*-------------------------------------------------------Encryption--------------------------------------------------------*
*#########################################################################################################################*/
static cc_result GetMachineID(cc_uint32* key) {
return ERR_NOT_SUPPORTED;
}
#endif

206
src/Window_PS1.c Normal file
View file

@ -0,0 +1,206 @@
#include "Core.h"
#if defined CC_BUILD_PS1
#include "Window.h"
#include "Platform.h"
#include "Input.h"
#include "Event.h"
#include "Graphics.h"
#include "String.h"
#include "Funcs.h"
#include "Bitmap.h"
#include "Errors.h"
#include "ExtMath.h"
#include "Logger.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <psxapi.h>
#include <psxetc.h>
#include <psxgte.h>
#include <psxgpu.h>
#include <psxpad.h>
#define SCREEN_XRES 320
#define SCREEN_YRES 240
static cc_bool launcherMode;
static char pad_buff[2][34];
struct _DisplayData DisplayInfo;
struct _WindowData WindowInfo;
void Window_Init(void) {
DisplayInfo.Width = SCREEN_XRES;
DisplayInfo.Height = SCREEN_YRES;
DisplayInfo.Depth = 4; // 32 bit
DisplayInfo.ScaleX = 1;
DisplayInfo.ScaleY = 1;
Window_Main.Width = DisplayInfo.Width;
Window_Main.Height = DisplayInfo.Height;
Window_Main.Focused = true;
Window_Main.Exists = true;
Input.Sources = INPUT_SOURCE_GAMEPAD;
DisplayInfo.ContentOffsetX = 10;
DisplayInfo.ContentOffsetY = 10;
// http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html
InitPAD(&pad_buff[0][0], 34, &pad_buff[1][0], 34);
pad_buff[0][0] = pad_buff[0][1] = 0xff;
pad_buff[1][0] = pad_buff[1][1] = 0xff;
StartPAD();
ChangeClearPAD(0);
}
void Window_Free(void) { }
void Window_Create3D(int width, int height) {
launcherMode = false;
}
void Window_SetTitle(const cc_string* title) { }
void Clipboard_GetText(cc_string* value) { }
void Clipboard_SetText(const cc_string* value) { }
int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; }
cc_result Window_EnterFullscreen(void) { return 0; }
cc_result Window_ExitFullscreen(void) { return 0; }
int Window_IsObscured(void) { return 0; }
void Window_Show(void) { }
void Window_SetSize(int width, int height) { }
void Window_RequestClose(void) {
Event_RaiseVoid(&WindowEvents.Closing);
}
/*########################################################################################################################*
*----------------------------------------------------Input processing-----------------------------------------------------*
*#########################################################################################################################*/
static void HandleButtons(int buttons) {
// Confusingly, it seems that when a bit is on, it means the button is NOT pressed
// So just flip the bits to make more sense
buttons = ~buttons;
Input_SetNonRepeatable(CCPAD_A, buttons & PAD_TRIANGLE);
Input_SetNonRepeatable(CCPAD_B, buttons & PAD_SQUARE);
Input_SetNonRepeatable(CCPAD_X, buttons & PAD_CROSS);
Input_SetNonRepeatable(CCPAD_Y, buttons & PAD_CIRCLE);
Input_SetNonRepeatable(CCPAD_START, buttons & PAD_START);
Input_SetNonRepeatable(CCPAD_SELECT, buttons & PAD_SELECT);
Input_SetNonRepeatable(CCPAD_LEFT, buttons & PAD_LEFT);
Input_SetNonRepeatable(CCPAD_RIGHT, buttons & PAD_RIGHT);
Input_SetNonRepeatable(CCPAD_UP, buttons & PAD_UP);
Input_SetNonRepeatable(CCPAD_DOWN, buttons & PAD_DOWN);
Input_SetNonRepeatable(CCPAD_L, buttons & PAD_L1);
Input_SetNonRepeatable(CCPAD_R, buttons & PAD_R1);
Input_SetNonRepeatable(CCPAD_ZL, buttons & PAD_L2);
Input_SetNonRepeatable(CCPAD_ZR, buttons & PAD_R2);
}
static void ProcessPadInput(PADTYPE* pad, double delta) {
HandleButtons(pad->btn);
}
void Window_ProcessEvents(double delta) {
PADTYPE* pad = (PADTYPE*)&pad_buff[0][0];
if (pad->stat == 0) ProcessPadInput(pad, delta);
}
void Cursor_SetPosition(int x, int y) { } // Makes no sense for PS Vita
void Window_EnableRawMouse(void) { Input.RawMode = true; }
void Window_UpdateRawMouse(void) { }
void Window_DisableRawMouse(void) { Input.RawMode = false; }
/*########################################################################################################################*
*------------------------------------------------------Framebuffer--------------------------------------------------------*
*#########################################################################################################################*/
void Window_Create2D(int width, int height) {
launcherMode = true;
}
static DISPENV disp;
static cc_uint16* fb;
void Window_AllocFramebuffer(struct Bitmap* bmp) {
SetDefDispEnv(&disp, 0, 0, SCREEN_XRES, SCREEN_YRES);
disp.isinter = 1;
PutDispEnv(&disp);
SetDispMask(1);
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");
fb = Mem_Alloc(bmp->width * bmp->height, 2, "real surface");
}
#define BGRA8_to_PS1(src) \
((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | 0x8000
void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
RECT rect;
rect.x = 0;
rect.y = 0;
rect.w = SCREEN_XRES;
rect.h = SCREEN_YRES;
HeapUsage usage;
GetHeapUsage(&usage);
Platform_Log4("%i / %i / %i / %i", &usage.total, &usage.heap, &usage.stack, &usage.alloc);
for (int y = 0; y < bmp->height; y++)
{
cc_uint32* src = bmp->scan0 + y * bmp->width;
cc_uint16* dst = fb + y * bmp->width;
for (int x = 0; x < bmp->width; x++) {
cc_uint8* color = (cc_uint8*)&src[x];
dst[x] = BGRA8_to_PS1(0);
}
}
Platform_Log4("%i / %i / %i / %i", &usage.total, &usage.heap, &usage.stack, &usage.alloc);
LoadImage(&rect, bmp->scan0);
DrawSync(0);
}
void Window_FreeFramebuffer(struct Bitmap* bmp) {
Mem_Free(bmp->scan0);
Mem_Free(fb);
}
/*########################################################################################################################*
*------------------------------------------------------Soft keyboard------------------------------------------------------*
*#########################################################################################################################*/
void Window_OpenKeyboard(struct OpenKeyboardArgs* args) { /* TODO implement */ }
void Window_SetKeyboardText(const cc_string* text) { }
void Window_CloseKeyboard(void) { /* TODO implement */ }
/*########################################################################################################################*
*-------------------------------------------------------Misc/Other--------------------------------------------------------*
*#########################################################################################################################*/
void Window_ShowDialog(const char* title, const char* msg) {
/* TODO implement */
Platform_LogConst(title);
Platform_LogConst(msg);
}
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}
#endif

View file

@ -70,6 +70,11 @@ int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* arg
// Consoles *sometimes* doesn't use argv[0] for program name and so argc will be 0
// (e.g. when running via some emulators)
if (!argc) return 0;
#ifdef CC_BUILD_PS1
// When running in DuckStation at least, argv was a five element array of empty strings ???
return 0;
#endif
argc--; argv++; // skip executable path argument
@ -215,4 +220,4 @@ cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) {
String_AppendAll(dst, header, min(dataLen, ENC_SIZE));
}
return 0;
}
}