mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
WIP PS3 stuff
This commit is contained in:
parent
e6d1f593d2
commit
7ece36c006
2
Makefile
2
Makefile
@ -147,6 +147,8 @@ psp:
|
||||
$(MAKE) -f src/Makefile_PSP PLAT=psp
|
||||
vita:
|
||||
$(MAKE) -f src/Makefile_vita PLAT=vita
|
||||
ps3:
|
||||
$(MAKE) -f src/Makefile_PS3 PLAT=ps3
|
||||
3ds:
|
||||
$(MAKE) -f src/Makefile_3DS PLAT=3ds
|
||||
wii:
|
||||
|
@ -292,6 +292,12 @@ typedef cc_uint8 cc_bool;
|
||||
#define CC_BUILD_DREAMCAST
|
||||
#define CC_BUILD_LOWMEM
|
||||
#undef CC_BUILD_FREETYPE
|
||||
#elif defined PLAT_PS3
|
||||
#define CC_BUILD_HTTPCLIENT
|
||||
#define CC_BUILD_OPENAL
|
||||
#define CC_BUILD_PS3
|
||||
#define CC_BUILD_LOWMEM
|
||||
#undef CC_BUILD_FREETYPE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -142,8 +142,6 @@ void Gfx_EndFrame(void) {
|
||||
}
|
||||
|
||||
void Gfx_OnWindowResize(void) {
|
||||
/* TODO: Eliminate this nasty hack.. */
|
||||
Game_UpdateDimensions();
|
||||
glViewport(0, 0, Game.Width, Game.Height);
|
||||
}
|
||||
|
||||
|
453
src/Graphics_PS3.c
Normal file
453
src/Graphics_PS3.c
Normal file
@ -0,0 +1,453 @@
|
||||
#include "Core.h"
|
||||
#if defined CC_BUILD_PS3
|
||||
#include "_GraphicsBase.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "Window.h"
|
||||
#include <malloc.h>
|
||||
#include <rsx/rsx.h>
|
||||
#include <sysutil/video.h>
|
||||
|
||||
/* Current format and size of vertices */
|
||||
static int gfx_stride, gfx_format = -1;
|
||||
static cc_bool renderingDisabled;
|
||||
static gcmContextData* context;
|
||||
static u32 cur_fb = 0;
|
||||
|
||||
#define CB_SIZE 0x100000 // TODO: smaller command buffer?
|
||||
#define HOST_SIZE (32 * 1024 * 1024)
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------- setup---------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static u32 color_pitch;
|
||||
static u32 color_offset[2];
|
||||
static u32* color_buffer[2];
|
||||
|
||||
static u32 depth_pitch;
|
||||
static u32 depth_offset;
|
||||
static u32* depth_buffer;
|
||||
|
||||
static void Gfx_FreeState(void) { FreeDefaultResources(); }
|
||||
static void Gfx_RestoreState(void) {
|
||||
InitDefaultResources();
|
||||
gfx_format = -1;/* TODO */
|
||||
|
||||
rsxSetColorMaskMrt(context, 0);
|
||||
rsxSetDepthFunc(context, GCM_LEQUAL);
|
||||
rsxSetClearDepthStencil(context, 0xFFFFFF);
|
||||
}
|
||||
|
||||
static void CreateContext(void) {
|
||||
void* host_addr = memalign(1024 * 1024, HOST_SIZE);
|
||||
rsxInit(&context, CB_SIZE, HOST_SIZE, host_addr);
|
||||
}
|
||||
|
||||
static void ConfigureVideo(void) {
|
||||
videoState state;
|
||||
videoGetState(0, 0, &state);
|
||||
|
||||
videoConfiguration vconfig = { 0 };
|
||||
vconfig.resolution = state.displayMode.resolution;
|
||||
vconfig.format = VIDEO_BUFFER_FORMAT_XRGB;
|
||||
vconfig.pitch = DisplayInfo.Width * sizeof(u32);
|
||||
|
||||
videoConfigure(0, &vconfig, NULL, 0);
|
||||
}
|
||||
|
||||
static void SetupBlendingState(void) {
|
||||
rsxSetBlendFunc(context, GCM_SRC_ALPHA, GCM_ONE_MINUS_SRC_ALPHA, GCM_SRC_ALPHA, GCM_ONE_MINUS_SRC_ALPHA);
|
||||
rsxSetBlendEquation(context, GCM_FUNC_ADD, GCM_FUNC_ADD);
|
||||
}
|
||||
|
||||
static void AllocColorSurface(u32 i) {
|
||||
color_pitch = DisplayInfo.Width * 4;
|
||||
color_buffer[i] = (u32*)rsxMemalign(64, DisplayInfo.Height * color_pitch);
|
||||
|
||||
rsxAddressToOffset(color_buffer[i], &color_offset[i]);
|
||||
gcmSetDisplayBuffer(i, color_offset[i], color_pitch,
|
||||
DisplayInfo.Width, DisplayInfo.Height);
|
||||
}
|
||||
|
||||
static void AllocDepthSurface(void) {
|
||||
depth_pitch = DisplayInfo.Width * 4;
|
||||
depth_buffer = (u32*)rsxMemalign(64, DisplayInfo.Height * depth_pitch);
|
||||
|
||||
rsxAddressToOffset(depth_buffer, &depth_offset);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------General---------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void SetRenderTarget(u32 index) {
|
||||
gcmSurface sf;
|
||||
|
||||
sf.colorFormat = GCM_SURFACE_X8R8G8B8;
|
||||
sf.colorTarget = GCM_SURFACE_TARGET_0;
|
||||
sf.colorLocation[0] = GCM_LOCATION_RSX;
|
||||
sf.colorOffset[0] = color_offset[index];
|
||||
sf.colorPitch[0] = color_pitch;
|
||||
|
||||
sf.colorLocation[1] = GCM_LOCATION_RSX;
|
||||
sf.colorLocation[2] = GCM_LOCATION_RSX;
|
||||
sf.colorLocation[3] = GCM_LOCATION_RSX;
|
||||
sf.colorOffset[1] = 0;
|
||||
sf.colorOffset[2] = 0;
|
||||
sf.colorOffset[3] = 0;
|
||||
sf.colorPitch[1] = 64;
|
||||
sf.colorPitch[2] = 64;
|
||||
sf.colorPitch[3] = 64;
|
||||
|
||||
sf.depthFormat = GCM_SURFACE_ZETA_Z24S8;
|
||||
sf.depthLocation = GCM_LOCATION_RSX;
|
||||
sf.depthOffset = depth_offset;
|
||||
sf.depthPitch = depth_pitch;
|
||||
|
||||
sf.type = GCM_SURFACE_TYPE_LINEAR;
|
||||
sf.antiAlias = GCM_SURFACE_CENTER_1;
|
||||
|
||||
sf.width = DisplayInfo.Width;
|
||||
sf.height = DisplayInfo.Height;
|
||||
sf.x = 0;
|
||||
sf.y = 0;
|
||||
|
||||
rsxSetSurface(context,&sf);
|
||||
}
|
||||
|
||||
void Gfx_Create(void) {
|
||||
// TODO rethink all this
|
||||
if (Gfx.Created) return;
|
||||
Gfx.MaxTexWidth = 1024;
|
||||
Gfx.MaxTexHeight = 1024;
|
||||
Gfx.Created = true;
|
||||
|
||||
// https://github.com/ps3dev/PSL1GHT/blob/master/ppu/include/rsx/rsx.h#L30
|
||||
CreateContext();
|
||||
ConfigureVideo();
|
||||
gcmSetFlipMode(GCM_FLIP_VSYNC);
|
||||
|
||||
AllocColorSurface(0);
|
||||
AllocColorSurface(1);
|
||||
AllocDepthSurface();
|
||||
gcmResetFlipStatus();
|
||||
|
||||
SetupBlendingState();
|
||||
Gfx_RestoreState();
|
||||
SetRenderTarget(cur_fb);
|
||||
}
|
||||
|
||||
cc_bool Gfx_TryRestoreContext(void) { return true; }
|
||||
|
||||
cc_bool Gfx_WarnIfNecessary(void) { return false; }
|
||||
|
||||
void Gfx_Free(void) {
|
||||
Gfx_FreeState();
|
||||
}
|
||||
|
||||
u32* Gfx_AllocImage(u32* offset, s32 w, s32 h) {
|
||||
u32* pixels = (u32*)rsxMemalign(64, w * h * 4);
|
||||
rsxAddressToOffset(pixels, offset);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
void Gfx_TransferImage(u32 offset, s32 w, s32 h) {
|
||||
rsxSetTransferImage(context, GCM_TRANSFER_LOCAL_TO_LOCAL,
|
||||
color_offset[cur_fb], color_pitch, -w/2, -h/2,
|
||||
offset, w * 4, 0, 0, w, h, 4);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------State management----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static PackedCol gfx_clearColor;
|
||||
void Gfx_SetFaceCulling(cc_bool enabled) {
|
||||
rsxSetCullFaceEnable(context, enabled);
|
||||
}
|
||||
|
||||
void Gfx_SetAlphaBlending(cc_bool enabled) {
|
||||
rsxSetBlendEnable(context, enabled);
|
||||
}
|
||||
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
|
||||
|
||||
void Gfx_ClearCol(PackedCol color) {
|
||||
rsxSetClearColor(context, color);
|
||||
}
|
||||
|
||||
void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
|
||||
unsigned mask = 0;
|
||||
if (r) mask |= GCM_COLOR_MASK_R;
|
||||
if (g) mask |= GCM_COLOR_MASK_G;
|
||||
if (b) mask |= GCM_COLOR_MASK_B;
|
||||
if (a) mask |= GCM_COLOR_MASK_A;
|
||||
|
||||
rsxSetColorMask(context, mask);
|
||||
}
|
||||
|
||||
void Gfx_SetDepthWrite(cc_bool enabled) {
|
||||
rsxSetDepthWriteEnable(context, enabled);
|
||||
}
|
||||
|
||||
void Gfx_SetDepthTest(cc_bool enabled) {
|
||||
rsxSetDepthTestEnable(context, enabled);
|
||||
}
|
||||
|
||||
void Gfx_SetTexturing(cc_bool enabled) { }
|
||||
|
||||
void Gfx_SetAlphaTest(cc_bool enabled) { /* TODO */ }
|
||||
|
||||
void Gfx_DepthOnlyRendering(cc_bool depthOnly) {/* TODO */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
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 = 0.1f;
|
||||
float c = (float)Cotangent(0.5f * fov);
|
||||
|
||||
/* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glfrustum */
|
||||
/* For a 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
|
||||
String_Format1(info, "-- Using PS3 (%i bit) --\n", &pointerSize);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
gfx_minFrameMs = minFrameMs;
|
||||
gfx_vsync = vsync;
|
||||
}
|
||||
|
||||
|
||||
// https://github.com/ps3dev/PSL1GHT/blob/master/ppu/include/rsx/rsx.h#L30
|
||||
static cc_bool everFlipped;
|
||||
void Gfx_BeginFrame(void) {
|
||||
// TODO: remove everFlipped
|
||||
if (everFlipped) {
|
||||
while (gcmGetFlipStatus() != 0) usleep(200);
|
||||
}
|
||||
|
||||
everFlipped = true;
|
||||
gcmResetFlipStatus();
|
||||
}
|
||||
|
||||
void Gfx_Clear(void) {
|
||||
rsxClearSurface(context, GCM_CLEAR_R | GCM_CLEAR_G | GCM_CLEAR_B | GCM_CLEAR_A
|
||||
| GCM_CLEAR_S | GCM_CLEAR_Z);
|
||||
}
|
||||
|
||||
void Gfx_EndFrame(void) {
|
||||
gcmSetFlip(context, cur_fb);
|
||||
rsxFlushBuffer(context);
|
||||
gcmSetWaitFlip(context);
|
||||
|
||||
cur_fb ^= 1;
|
||||
SetRenderTarget(cur_fb);
|
||||
|
||||
if (gfx_minFrameMs) LimitFPS();
|
||||
}
|
||||
|
||||
void Gfx_OnWindowResize(void) {/* TODO */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Index buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void* gfx_vertices;
|
||||
static int vb_size;
|
||||
|
||||
GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) {
|
||||
return 1;/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_BindIb(GfxResourceID ib) { }
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
void* data = memalign(16, count * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
//return Mem_Alloc(count, strideSizes[fmt], "gfx VB");/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb;/* TODO */ }
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
GfxResourceID data = *vb;/* TODO */
|
||||
if (data) Mem_Free(data);
|
||||
*vb = 0;
|
||||
}
|
||||
|
||||
void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
vb_size = count * strideSizes[fmt];/* TODO */
|
||||
return vb;
|
||||
}
|
||||
|
||||
void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
gfx_vertices = vb;/* TODO */
|
||||
//sceKernelDcacheWritebackInvalidateRange(vb, vb_size);
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
void* data = memalign(16, maxVertices * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;/* TODO */
|
||||
//return Mem_Alloc(maxVertices, strideSizes[fmt], "gfx VB");
|
||||
}
|
||||
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
vb_size = count * strideSizes[fmt];
|
||||
return vb; /* TODO */
|
||||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
gfx_vertices = vb; /* TODO */
|
||||
//dcache_flush_range(vb, vb_size);
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
gfx_vertices = vb;/* TODO */
|
||||
Mem_Copy(vb, vertices, vCount * gfx_stride);
|
||||
//dcache_flush_range(vertices, vCount * gfx_stride);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_BindTexture(GfxResourceID texId) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_EnableMipmaps(void) { }
|
||||
void Gfx_DisableMipmaps(void) { }
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
return 1;/* TODO */
|
||||
}
|
||||
|
||||
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) {
|
||||
Gfx_UpdateTexture(texId, x, y, part, part->width, mipmaps);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------State management----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static PackedCol gfx_fogColor;
|
||||
static float gfx_fogEnd = 16.0f, gfx_fogDensity = 1.0f;
|
||||
static FogFunc gfx_fogMode = -1;
|
||||
|
||||
void Gfx_SetFog(cc_bool enabled) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_SetFogCol(PackedCol color) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_SetFogDensity(float value) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_SetFogEnd(float value) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_SetFogMode(FogFunc func) {/* TODO */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
||||
void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_LoadIdentityMatrix(MatrixType type) {
|
||||
Gfx_LoadMatrix(type, &Matrix_Identity);
|
||||
}
|
||||
|
||||
|
||||
void Gfx_EnableTextureOffset(float x, float y) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DisableTextureOffset(void) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||
if (fmt == gfx_format) return;
|
||||
gfx_format = fmt;
|
||||
gfx_stride = strideSizes[fmt];/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_Lines(int verticesCount) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris(int verticesCount) {/* TODO */
|
||||
}
|
||||
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {/* TODO */
|
||||
}
|
||||
#endif
|
124
src/Makefile_PS3
Normal file
124
src/Makefile_PS3
Normal file
@ -0,0 +1,124 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(PSL1GHT)),)
|
||||
$(error "Please set PSL1GHT in your environment. export PSL1GHT=<path>")
|
||||
endif
|
||||
|
||||
include $(PSL1GHT)/ppu_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := ClassiCube-PS3
|
||||
BUILD := build-ps3
|
||||
SOURCES := src
|
||||
INCLUDES :=
|
||||
|
||||
TITLE := ClassiCube
|
||||
APPID := CUBE00200
|
||||
CONTENTID := UP0001-$(APPID)_00-0000000000000000
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -O2 -DPLAT_PS3 -Wall -mcpu=cell $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lrsx -lgcm_sys -lio -lsysutil -lrt -llv2 -lm -lnet -lsysmodule
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export BUILDDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
export OFILES := $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES), -I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(LIBPSL1GHT_INC) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||
$(LIBPSL1GHT_LIB)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/src/Makefile_PS3
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).self
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).self: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule links in binary data with the .bin extension
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
@ -6,21 +6,21 @@
|
||||
*/
|
||||
|
||||
typedef cc_uint32 PackedCol;
|
||||
#if defined CC_BUILD_D3D9 || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST
|
||||
#define PACKEDCOL_B_SHIFT 0
|
||||
#define PACKEDCOL_G_SHIFT 8
|
||||
#define PACKEDCOL_R_SHIFT 16
|
||||
#define PACKEDCOL_A_SHIFT 24
|
||||
#if defined CC_BUILD_D3D9 || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST || defined CC_BUILD_PS3
|
||||
#define PACKEDCOL_B_SHIFT 0
|
||||
#define PACKEDCOL_G_SHIFT 8
|
||||
#define PACKEDCOL_R_SHIFT 16
|
||||
#define PACKEDCOL_A_SHIFT 24
|
||||
#elif defined CC_BIG_ENDIAN
|
||||
#define PACKEDCOL_R_SHIFT 24
|
||||
#define PACKEDCOL_G_SHIFT 16
|
||||
#define PACKEDCOL_B_SHIFT 8
|
||||
#define PACKEDCOL_A_SHIFT 0
|
||||
#define PACKEDCOL_R_SHIFT 24
|
||||
#define PACKEDCOL_G_SHIFT 16
|
||||
#define PACKEDCOL_B_SHIFT 8
|
||||
#define PACKEDCOL_A_SHIFT 0
|
||||
#else
|
||||
#define PACKEDCOL_R_SHIFT 0
|
||||
#define PACKEDCOL_G_SHIFT 8
|
||||
#define PACKEDCOL_B_SHIFT 16
|
||||
#define PACKEDCOL_A_SHIFT 24
|
||||
#define PACKEDCOL_R_SHIFT 0
|
||||
#define PACKEDCOL_G_SHIFT 8
|
||||
#define PACKEDCOL_B_SHIFT 16
|
||||
#define PACKEDCOL_A_SHIFT 24
|
||||
#endif
|
||||
|
||||
#define PACKEDCOL_R_MASK (0xFFU << PACKEDCOL_R_SHIFT)
|
||||
|
476
src/Platform_PS3.c
Normal file
476
src/Platform_PS3.c
Normal file
@ -0,0 +1,476 @@
|
||||
#include "Core.h"
|
||||
#if defined PLAT_PS3
|
||||
|
||||
#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 <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
#include <signal.h>
|
||||
#include <net/net.h>
|
||||
#include <net/poll.h>
|
||||
#include <ppu-lv2.h>
|
||||
#include <sys/lv2errno.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/thread.h>
|
||||
#include <sys/systime.h>
|
||||
#include <sys/tty.h>
|
||||
#include "_PlatformConsole.h"
|
||||
|
||||
const cc_result ReturnCode_FileShareViolation = 1000000000; // not used
|
||||
const cc_result ReturnCode_FileNotFound = 0x80010006; // ENOENT;
|
||||
//const cc_result ReturnCode_SocketInProgess = 0x80010032; // EINPROGRESS
|
||||
//const cc_result ReturnCode_SocketWouldBlock = 0x80010001; // EWOULDBLOCK;
|
||||
const cc_result ReturnCode_DirectoryExists = 0x80010014; // EEXIST
|
||||
|
||||
const cc_result ReturnCode_SocketInProgess = NET_EINPROGRESS;
|
||||
const cc_result ReturnCode_SocketWouldBlock = NET_EWOULDBLOCK;
|
||||
const char* Platform_AppNameSuffix = " PS3";
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Logging/Time-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Platform_Log(const char* msg, int len) {
|
||||
u32 done = 0;
|
||||
sysTtyWrite(STDOUT_FILENO, msg, len, &done);
|
||||
sysTtyWrite(STDOUT_FILENO, "\n", 1, &done);
|
||||
}
|
||||
|
||||
#define UnixTime_TotalMS(time) ((cc_uint64)time.tv_sec * 1000 + UNIX_EPOCH + (time.tv_usec / 1000))
|
||||
TimeMS DateTime_CurrentUTC_MS(void) {
|
||||
struct timeval cur;
|
||||
gettimeofday(&cur, NULL);
|
||||
return UnixTime_TotalMS(cur);
|
||||
}
|
||||
|
||||
void DateTime_CurrentLocal(struct DateTime* t) {
|
||||
struct timeval cur;
|
||||
struct tm loc_time;
|
||||
gettimeofday(&cur, NULL);
|
||||
localtime_r(&cur.tv_sec, &loc_time);
|
||||
|
||||
t->year = loc_time.tm_year + 1900;
|
||||
t->month = loc_time.tm_mon + 1;
|
||||
t->day = loc_time.tm_mday;
|
||||
t->hour = loc_time.tm_hour;
|
||||
t->minute = loc_time.tm_min;
|
||||
t->second = loc_time.tm_sec;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Stopwatch--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#define NS_PER_SEC 1000000000ULL
|
||||
|
||||
cc_uint64 Stopwatch_Measure(void) {
|
||||
u64 sec, nsec;
|
||||
sysGetCurrentTime(&sec, &nsec);
|
||||
return sec * NS_PER_SEC + nsec;
|
||||
}
|
||||
|
||||
cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
|
||||
if (end < beg) return 0;
|
||||
return (end - beg) / 1000;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Directory/File------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
cc_result Directory_Create(const cc_string* path) {
|
||||
char str[NATIVE_STR_LEN];
|
||||
String_EncodeUtf8(str, path);
|
||||
/* read/write/search permissions for owner and group, and with read/search permissions for others. */
|
||||
/* TODO: Is the default mode in all cases */
|
||||
return mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
int File_Exists(const cc_string* path) {
|
||||
char str[NATIVE_STR_LEN];
|
||||
struct stat sb;
|
||||
String_EncodeUtf8(str, path);
|
||||
return stat(str, &sb) == 0 && S_ISREG(sb.st_mode);
|
||||
}
|
||||
|
||||
cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) {
|
||||
cc_string path; char pathBuffer[FILENAME_SIZE];
|
||||
char str[NATIVE_STR_LEN];
|
||||
DIR* dirPtr;
|
||||
struct dirent* entry;
|
||||
char* src;
|
||||
int len, res, is_dir;
|
||||
|
||||
String_EncodeUtf8(str, dirPath);
|
||||
dirPtr = opendir(str);
|
||||
if (!dirPtr) return errno;
|
||||
|
||||
/* POSIX docs: "When the end of the directory is encountered, a null pointer is returned and errno is not changed." */
|
||||
/* errno is sometimes leftover from previous calls, so always reset it before readdir gets called */
|
||||
errno = 0;
|
||||
String_InitArray(path, pathBuffer);
|
||||
|
||||
while ((entry = readdir(dirPtr))) {
|
||||
path.length = 0;
|
||||
String_Format1(&path, "%s/", dirPath);
|
||||
|
||||
/* ignore . and .. entry */
|
||||
src = entry->d_name;
|
||||
if (src[0] == '.' && src[1] == '\0') continue;
|
||||
if (src[0] == '.' && src[1] == '.' && src[2] == '\0') continue;
|
||||
|
||||
len = String_Length(src);
|
||||
String_AppendUtf8(&path, src, len);
|
||||
|
||||
#if defined CC_BUILD_HAIKU || defined CC_BUILD_SOLARIS || defined CC_BUILD_IRIX || defined CC_BUILD_BEOS
|
||||
{
|
||||
char full_path[NATIVE_STR_LEN];
|
||||
struct stat sb;
|
||||
String_EncodeUtf8(full_path, &path);
|
||||
is_dir = stat(full_path, &sb) == 0 && S_ISDIR(sb.st_mode);
|
||||
}
|
||||
#else
|
||||
is_dir = entry->d_type == DT_DIR;
|
||||
/* TODO: fallback to stat when this fails */
|
||||
#endif
|
||||
|
||||
if (is_dir) {
|
||||
res = Directory_Enum(&path, obj, callback);
|
||||
if (res) { closedir(dirPtr); return res; }
|
||||
} else {
|
||||
callback(&path, obj);
|
||||
}
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
res = errno; /* return code from readdir */
|
||||
closedir(dirPtr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static cc_result File_Do(cc_file* file, const cc_string* path, int mode) {
|
||||
char str[NATIVE_STR_LEN];
|
||||
String_EncodeUtf8(str, path);
|
||||
*file = open(str, mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
return *file == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Open(cc_file* file, const cc_string* path) {
|
||||
return File_Do(file, path, O_RDONLY);
|
||||
}
|
||||
cc_result File_Create(cc_file* file, const cc_string* path) {
|
||||
return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC);
|
||||
}
|
||||
cc_result File_OpenOrCreate(cc_file* file, const cc_string* path) {
|
||||
return File_Do(file, path, O_RDWR | O_CREAT);
|
||||
}
|
||||
|
||||
cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) {
|
||||
*bytesRead = read(file, data, count);
|
||||
return *bytesRead == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) {
|
||||
*bytesWrote = write(file, data, count);
|
||||
return *bytesWrote == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Close(cc_file file) {
|
||||
return close(file) == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Seek(cc_file file, int offset, int seekType) {
|
||||
static cc_uint8 modes[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
|
||||
return lseek(file, offset, modes[seekType]) == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Position(cc_file file, cc_uint32* pos) {
|
||||
*pos = lseek(file, 0, SEEK_CUR);
|
||||
return *pos == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
cc_result File_Length(cc_file file, cc_uint32* len) {
|
||||
struct stat st;
|
||||
if (fstat(file, &st) == -1) { *len = -1; return errno; }
|
||||
*len = st.st_size; return 0;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Threading--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Thread_Sleep(cc_uint32 milliseconds) {
|
||||
sysUsleep(milliseconds * 1000);
|
||||
}
|
||||
|
||||
static void ExecThread(void* param) {
|
||||
((Thread_StartFunc)param)();
|
||||
}
|
||||
#define STACK_SIZE (128 * 1024)
|
||||
|
||||
void* Thread_Create(Thread_StartFunc func) {
|
||||
return Mem_Alloc(1, sizeof(sys_ppu_thread_t), "thread");
|
||||
}
|
||||
|
||||
void Thread_Start2(void* handle, Thread_StartFunc func) {
|
||||
sys_ppu_thread_t* thread = (sys_ppu_thread_t*)handle;
|
||||
int res = sysThreadCreate(thread, ExecThread, (void*)func,
|
||||
0, STACK_SIZE, THREAD_JOINABLE, "CC thread");
|
||||
if (res) Logger_Abort2(res, "Creating thread");
|
||||
}
|
||||
|
||||
void Thread_Detach(void* handle) {
|
||||
sys_ppu_thread_t* thread = (sys_ppu_thread_t*)handle;
|
||||
int res = sysThreadDetach(*thread);
|
||||
if (res) Logger_Abort2(res, "Detaching thread");
|
||||
Mem_Free(thread);
|
||||
}
|
||||
|
||||
void Thread_Join(void* handle) {
|
||||
u64 retVal;
|
||||
sys_ppu_thread_t* thread = (sys_ppu_thread_t*)handle;
|
||||
int res = sysThreadJoin(*thread, &retVal);
|
||||
if (res) Logger_Abort2(res, "Joining thread");
|
||||
Mem_Free(thread);
|
||||
}
|
||||
|
||||
void* Mutex_Create(void) {
|
||||
sys_mutex_attr_t attr;
|
||||
sysMutexAttrInitialize(attr);
|
||||
|
||||
sys_mutex_t* mutex = (sys_mutex_t*)Mem_Alloc(1, sizeof(sys_mutex_t), "mutex");
|
||||
int res = sysMutexCreate(mutex, &attr);
|
||||
if (res) Logger_Abort2(res, "Creating mutex");
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void Mutex_Free(void* handle) {
|
||||
sys_mutex_t* mutex = (sys_mutex_t*)handle;
|
||||
int res = sysMutexDestroy(*mutex);
|
||||
if (res) Logger_Abort2(res, "Destroying mutex");
|
||||
Mem_Free(mutex);
|
||||
}
|
||||
|
||||
void Mutex_Lock(void* handle) {
|
||||
sys_mutex_t* mutex = (sys_mutex_t*)handle;
|
||||
int res = sysMutexLock(*mutex, 0);
|
||||
if (res) Logger_Abort2(res, "Locking mutex");
|
||||
}
|
||||
|
||||
void Mutex_Unlock(void* handle) {
|
||||
sys_mutex_t* mutex = (sys_mutex_t*)handle;
|
||||
int res = sysMutexUnlock(*mutex);
|
||||
if (res) Logger_Abort2(res, "Unlocking mutex");
|
||||
}
|
||||
|
||||
void* Waitable_Create(void) {
|
||||
sys_sem_attr_t attr = { 0 };
|
||||
attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL;
|
||||
attr.attr_pshared = SYS_SEM_ATTR_PSHARED;
|
||||
|
||||
sys_sem_t* sem = (sys_sem_t*)Mem_Alloc(1, sizeof(sys_sem_t), "waitable");
|
||||
int res = sysSemCreate(sem, &attr, 0, 1000000);
|
||||
if (res) Logger_Abort2(res, "Creating waitable");
|
||||
|
||||
return sem;
|
||||
}
|
||||
|
||||
void Waitable_Free(void* handle) {
|
||||
sys_sem_t* sem = (sys_sem_t*)handle;
|
||||
|
||||
int res = sysSemDestroy(*sem);
|
||||
if (res) Logger_Abort2(res, "Destroying waitable");
|
||||
Mem_Free(sem);
|
||||
}
|
||||
|
||||
void Waitable_Signal(void* handle) {
|
||||
sys_sem_t* sem = (sys_sem_t*)handle;
|
||||
int res = sysSemPost(*sem, 1);
|
||||
if (res) Logger_Abort2(res, "Signalling event");
|
||||
}
|
||||
|
||||
void Waitable_Wait(void* handle) {
|
||||
sys_sem_t* sem = (sys_sem_t*)handle;
|
||||
int res = sysSemWait(*sem, 0);
|
||||
if (res) Logger_Abort2(res, "Waitable wait");
|
||||
}
|
||||
|
||||
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
|
||||
sys_sem_t* sem = (sys_sem_t*)handle;
|
||||
int res = sysSemWait(*sem, milliseconds * 1000);
|
||||
if (res) Logger_Abort2(res, "Waitable wait for");
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Socket----------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
union SocketAddress {
|
||||
struct sockaddr raw;
|
||||
struct sockaddr_in v4;
|
||||
};
|
||||
|
||||
static int ParseHost(union SocketAddress* addr, const char* host) {
|
||||
struct net_hostent* res = netGetHostByName(host);
|
||||
if (!res) return net_h_errno;
|
||||
|
||||
// Must have at least one IPv4 address
|
||||
if (res->h_addrtype != AF_INET) return ERR_INVALID_ARGUMENT;
|
||||
if (!res->h_addr_list) return ERR_INVALID_ARGUMENT;
|
||||
|
||||
// TODO probably wrong....
|
||||
addr->v4.sin_addr = *(struct in_addr*)&res->h_addr_list;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ParseAddress(union SocketAddress* addr, const cc_string* address) {
|
||||
char str[NATIVE_STR_LEN];
|
||||
String_EncodeUtf8(str, address);
|
||||
|
||||
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0;
|
||||
return ParseHost(addr, str);
|
||||
}
|
||||
|
||||
int Socket_ValidAddress(const cc_string* address) {
|
||||
union SocketAddress addr;
|
||||
return ParseAddress(&addr, address) == 0;
|
||||
}
|
||||
|
||||
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
|
||||
union SocketAddress addr;
|
||||
int res;
|
||||
|
||||
*s = -1;
|
||||
res = ParseAddress(&addr, address);
|
||||
if (res) return res;
|
||||
|
||||
res = sysNetSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (res < 0) return res;
|
||||
*s = res;
|
||||
|
||||
// TODO: RPCS3 makes sockets non blocking by default anyways ?
|
||||
/*if (nonblocking) {
|
||||
int blocking_raw = -1;
|
||||
ioctl(*s, FIONBIO, &blocking_raw);
|
||||
}*/
|
||||
|
||||
addr.v4.sin_family = AF_INET;
|
||||
addr.v4.sin_port = htons(port);
|
||||
|
||||
return sysNetConnect(*s, &addr.raw, sizeof(addr.v4));
|
||||
}
|
||||
|
||||
cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
|
||||
int res = sysNetRecvfrom(s, data, count, 0, NULL, NULL);
|
||||
if (res < 0) return res;
|
||||
|
||||
*modified = res; return 0;
|
||||
}
|
||||
|
||||
cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
|
||||
int res = sysNetSendto(s, data, count, 0, NULL, 0);
|
||||
if (res < 0) return res;
|
||||
|
||||
*modified = res; return 0;
|
||||
}
|
||||
|
||||
void Socket_Close(cc_socket s) {
|
||||
sysNetShutdown(s, SHUT_RDWR);
|
||||
sysNetClose(s);
|
||||
}
|
||||
|
||||
LV2_SYSCALL CC_sysNetPoll(struct pollfd* fds, s32 nfds, s32 ms)
|
||||
{
|
||||
lv2syscall3(715, (u64)fds, nfds, ms);
|
||||
return_to_user_prog(s32);
|
||||
}
|
||||
|
||||
static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) {
|
||||
struct pollfd pfd;
|
||||
int flags, res;
|
||||
|
||||
pfd.fd = s;
|
||||
pfd.events = mode == SOCKET_POLL_READ ? POLLIN : POLLOUT;
|
||||
|
||||
res = CC_sysNetPoll(&pfd, 1, 0);
|
||||
if (res) return res;
|
||||
|
||||
/* to match select, closed socket still counts as readable */
|
||||
flags = mode == SOCKET_POLL_READ ? (POLLIN | POLLHUP) : POLLOUT;
|
||||
*success = (pfd.revents & flags) != 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) {
|
||||
return Socket_Poll(s, SOCKET_POLL_READ, readable);
|
||||
}
|
||||
|
||||
cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
|
||||
socklen_t resultSize = sizeof(socklen_t);
|
||||
cc_result res = Socket_Poll(s, SOCKET_POLL_WRITE, writable);
|
||||
if (res || *writable) return res;
|
||||
|
||||
/* https://stackoverflow.com/questions/29479953/so-error-value-after-successful-socket-operation */
|
||||
netGetSockOpt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Platform---------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
cc_result Process_StartOpen(const cc_string* args) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void Platform_Init(void) {
|
||||
netInitialize();
|
||||
}
|
||||
|
||||
void Platform_Free(void) { }
|
||||
|
||||
cc_bool Platform_DescribeError(cc_result res, cc_string* dst) {
|
||||
char chars[NATIVE_STR_LEN];
|
||||
int len;
|
||||
|
||||
/* For unrecognised error codes, strerror_r might return messages */
|
||||
/* such as 'No error information', which is not very useful */
|
||||
/* (could check errno here but quicker just to skip entirely) */
|
||||
if (res >= 1000) return false;
|
||||
|
||||
len = strerror_r(res, chars, NATIVE_STR_LEN);
|
||||
if (len == -1) return false;
|
||||
|
||||
len = String_CalcLen(chars, NATIVE_STR_LEN);
|
||||
String_AppendUtf8(dst, chars, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Encryption--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static cc_result GetMachineID(cc_uint32* key) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif
|
176
src/Window_PS3.c
Normal file
176
src/Window_PS3.c
Normal file
@ -0,0 +1,176 @@
|
||||
#include "Core.h"
|
||||
#if defined CC_BUILD_PS3
|
||||
#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 <io/pad.h>
|
||||
#include <sysutil/video.h>
|
||||
static cc_bool launcherMode;
|
||||
static padInfo pad_info;
|
||||
static padData pad_data;
|
||||
|
||||
struct _DisplayData DisplayInfo;
|
||||
struct _WinData WindowInfo;
|
||||
// no DPI scaling on PS Vita
|
||||
int Display_ScaleX(int x) { return x; }
|
||||
int Display_ScaleY(int y) { return y; }
|
||||
|
||||
void Window_Init(void) {
|
||||
videoState state;
|
||||
videoResolution resolution;
|
||||
|
||||
videoGetState(0, 0, &state);
|
||||
videoGetResolution(state.displayMode.resolution, &resolution);
|
||||
|
||||
DisplayInfo.Width = resolution.width;
|
||||
DisplayInfo.Height = resolution.height;
|
||||
DisplayInfo.Depth = 4; // 32 bit
|
||||
DisplayInfo.ScaleX = 1;
|
||||
DisplayInfo.ScaleY = 1;
|
||||
|
||||
WindowInfo.Width = resolution.width;
|
||||
WindowInfo.Height = resolution.height;
|
||||
WindowInfo.Focused = true;
|
||||
WindowInfo.Exists = true;
|
||||
|
||||
Input.Sources = INPUT_SOURCE_GAMEPAD;
|
||||
ioPadInit(7);
|
||||
}
|
||||
|
||||
void Window_Create2D(int width, int height) {
|
||||
launcherMode = true;
|
||||
Gfx_Create(); // launcher also uses RSX to draw
|
||||
}
|
||||
|
||||
void Window_Create3D(int width, int height) {
|
||||
launcherMode = false;
|
||||
}
|
||||
|
||||
void Window_SetTitle(const cc_string* title) { }
|
||||
void Clipboard_GetText(cc_string* value) { } // TODO sceClipboardGetText
|
||||
void Clipboard_SetText(const cc_string* value) { } // TODO sceClipboardSetText
|
||||
|
||||
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_Close(void) {
|
||||
/* TODO implement */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Input processing-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void HandleButtons(padData* data) {
|
||||
Input_SetNonRepeatable(CCPAD_A, data->BTN_TRIANGLE);
|
||||
Input_SetNonRepeatable(CCPAD_B, data->BTN_SQUARE);
|
||||
Input_SetNonRepeatable(CCPAD_X, data->BTN_CROSS);
|
||||
Input_SetNonRepeatable(CCPAD_Y, data->BTN_CIRCLE);
|
||||
|
||||
Input_SetNonRepeatable(CCPAD_START, data->BTN_START);
|
||||
Input_SetNonRepeatable(CCPAD_SELECT, data->BTN_SELECT);
|
||||
|
||||
Input_SetNonRepeatable(CCPAD_LEFT, data->BTN_LEFT);
|
||||
Input_SetNonRepeatable(CCPAD_RIGHT, data->BTN_RIGHT);
|
||||
Input_SetNonRepeatable(CCPAD_UP, data->BTN_UP);
|
||||
Input_SetNonRepeatable(CCPAD_DOWN, data->BTN_DOWN);
|
||||
|
||||
Input_SetNonRepeatable(CCPAD_L, data->BTN_L1);
|
||||
Input_SetNonRepeatable(CCPAD_R, data->BTN_R1);
|
||||
Input_SetNonRepeatable(CCPAD_ZL, data->BTN_L2);
|
||||
Input_SetNonRepeatable(CCPAD_ZR, data->BTN_R2);
|
||||
}
|
||||
|
||||
static void ProcessPadInput(double delta, padData* pad) {
|
||||
HandleButtons(pad);
|
||||
//if (Input.RawMode)
|
||||
// ProcessCircleInput(&pad, delta);
|
||||
}
|
||||
|
||||
void Window_ProcessEvents(double delta) {
|
||||
ioPadGetInfo(&pad_info);
|
||||
|
||||
if (pad_info.status[0]) {
|
||||
ioPadGetData(0, &pad_data);
|
||||
ProcessPadInput(delta, &pad_data);
|
||||
}
|
||||
}
|
||||
|
||||
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--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static struct Bitmap fb_bmp;
|
||||
static u32 fb_offset;
|
||||
|
||||
extern u32* Gfx_AllocImage(u32* offset, s32 w, s32 h);
|
||||
extern void Gfx_TransferImage(u32 offset, s32 w, s32 h);
|
||||
|
||||
void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
||||
u32* pixels = Gfx_AllocImage(&fb_offset, bmp->width, bmp->height);
|
||||
bmp->scan0 = pixels;
|
||||
fb_bmp = *bmp;
|
||||
}
|
||||
|
||||
void Window_DrawFramebuffer(Rect2D r) {
|
||||
// TODO test
|
||||
Thread_Sleep(1000);
|
||||
Platform_Log1("FRAME START (%h)", &fb_offset);
|
||||
Gfx_BeginFrame();
|
||||
Gfx_ClearCol(PackedCol_Make(0x40, 0x60, 0x80, 0xFF));
|
||||
Gfx_Clear();
|
||||
Gfx_TransferImage(fb_offset, fb_bmp.width, fb_bmp.height);
|
||||
Gfx_EndFrame();
|
||||
Platform_LogConst("FRAME END");
|
||||
}
|
||||
|
||||
void Window_FreeFramebuffer(struct Bitmap* bmp) {
|
||||
//Mem_Free(bmp->scan0);
|
||||
/* TODO free framebuffer */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------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
|
Loading…
x
Reference in New Issue
Block a user