mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 09:01:57 -05:00
Broken PS1 port
This commit is contained in:
parent
8bfe004d71
commit
eff5ddabd2
13 changed files with 871 additions and 3 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -72,6 +72,10 @@ ClassiCube*
|
|||
screenshots
|
||||
fontscache.txt
|
||||
|
||||
# CMake files
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
|
||||
#GCC object files
|
||||
*.o
|
||||
|
||||
|
|
3
Makefile
3
Makefile
|
@ -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
21
misc/ps1/CMakeLists.txt
Normal 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
|
||||
)
|
26
misc/ps1/CMakePresets.json
Normal file
26
misc/ps1/CMakePresets.json
Normal 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
83
misc/ps1/iso.xml
Normal 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
4
misc/ps1/system.cnf
Normal file
|
@ -0,0 +1,4 @@
|
|||
BOOT=cdrom:\template.exe;1
|
||||
TCB=4
|
||||
EVENT=10
|
||||
STACK=801FFFF0
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
272
src/Graphics_PS1.c
Normal 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
229
src/Platform_PS1.c
Normal 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
206
src/Window_PS1.c
Normal 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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue