diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj
index 526fae5ac..35ca0b84d 100644
--- a/src/ClassiCube.vcxproj
+++ b/src/ClassiCube.vcxproj
@@ -469,6 +469,7 @@
+
@@ -491,6 +492,7 @@
+
@@ -529,6 +531,7 @@
+
diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters
index 0efffd4e7..4e46449fb 100644
--- a/src/ClassiCube.vcxproj.filters
+++ b/src/ClassiCube.vcxproj.filters
@@ -662,9 +662,18 @@
Source Files\Graphics
+
+ Source Files\Graphics
+
+
+ Source Files\Platform
+
+
+ Source Files\Window
+
-
+
Resource Files
diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c
index eadf17ee9..7ea4cacf6 100644
--- a/src/Graphics_PS3.c
+++ b/src/Graphics_PS3.c
@@ -19,7 +19,92 @@ static u32 cur_fb = 0;
/*########################################################################################################################*
-*---------------------------------------------------------- setup---------------------------------------------------------*
+*----------------------------------------------------- Vertex Shaders ----------------------------------------------------*
+*#########################################################################################################################*/
+typedef struct CCVertexProgram {
+ rsxVertexProgram* prog;
+ void* ucode;
+ rsxProgramConst* mvp;
+} VertexProgram;
+
+extern const u8 vs_textured_vpo[];
+extern const u8 vs_coloured_vpo[];
+
+static VertexProgram VP_list[2];
+static VertexProgram* VP_active;
+
+
+static void VP_Load(VertexProgram* vp, const u8* source) {
+ vp->prog = (rsxVertexProgram*)source;
+ u32 size = 0;
+ rsxVertexProgramGetUCode(vp->prog, &vp->ucode, &size);
+ vp->mvp = rsxVertexProgramGetConst(vp->prog, "mvp");
+
+ Platform_Log1("VP shader size: %i", &size);
+}
+
+static void LoadVertexPrograms(void) {
+ VP_Load(&VP_list[0], vs_coloured_vpo);
+ VP_Load(&VP_list[1], vs_textured_vpo);
+}
+
+static void VP_SwitchActive(void) {
+ int index = gfx_format == VERTEX_FORMAT_TEXTURED ? 1 : 0;
+
+ VertexProgram* VP = &VP_list[index];
+ if (VP == VP_active) return;
+ VP_active = VP;
+
+ rsxLoadVertexProgram(context, VP->prog, VP->ucode);
+}
+
+
+/*########################################################################################################################*
+*---------------------------------------------------- Fragment Shaders ---------------------------------------------------*
+*#########################################################################################################################*/
+typedef struct CCFragmentProgram {
+ rsxFragmentProgram* prog;
+ void* ucode;
+ u32* buffer;
+ u32 offset;
+} FragmentProgram;
+
+extern const u8 ps_textured_fpo[];
+extern const u8 ps_coloured_fpo[];
+
+static FragmentProgram FP_list[2];
+static FragmentProgram* FP_active;
+
+
+static void FP_Load(FragmentProgram* fp, const u8* source) {
+ fp->prog = (rsxFragmentProgram*)source;
+ u32 size = 0;
+ rsxFragmentProgramGetUCode(fp->prog, &fp->ucode, &size);
+
+ Platform_Log1("FP shader size: %i", &size);
+ fp->buffer = (u32*)rsxMemalign(128, size);
+ Mem_Copy(fp->buffer, fp->ucode, size);
+ rsxAddressToOffset(fp->buffer, &fp->offset);
+}
+
+static void LoadFragmentPrograms(void) {
+ FP_Load(&FP_list[0], ps_textured_fpo);
+ FP_Load(&FP_list[1], ps_coloured_fpo);
+}
+
+static void FP_SwitchActive(void) {
+ int index = gfx_format == VERTEX_FORMAT_TEXTURED ? 1 : 0;
+
+ FragmentProgram* FP = &FP_list[index];
+ if (FP == FP_active) return;
+ FP_active = FP;
+
+ rsxLoadFragmentProgramLocation(context, FP->prog, FP->offset, GCM_LOCATION_RSX);
+}
+
+
+/*########################################################################################################################*
+*---------------------------------------------------------- Setup---------------------------------------------------------*
*#########################################################################################################################*/
static u32 color_pitch;
static u32 color_offset[2];
@@ -37,6 +122,13 @@ static void Gfx_RestoreState(void) {
rsxSetColorMaskMrt(context, 0);
rsxSetDepthFunc(context, GCM_LEQUAL);
rsxSetClearDepthStencil(context, 0xFFFFFF);
+
+ rsxSetUserClipPlaneControl(context,GCM_USER_CLIP_PLANE_DISABLE,
+ GCM_USER_CLIP_PLANE_DISABLE,
+ GCM_USER_CLIP_PLANE_DISABLE,
+ GCM_USER_CLIP_PLANE_DISABLE,
+ GCM_USER_CLIP_PLANE_DISABLE,
+ GCM_USER_CLIP_PLANE_DISABLE);
}
static void CreateContext(void) {
@@ -136,6 +228,9 @@ void Gfx_Create(void) {
SetupBlendingState();
Gfx_RestoreState();
SetRenderTarget(cur_fb);
+
+ LoadVertexPrograms();
+ LoadFragmentPrograms();
}
cc_bool Gfx_TryRestoreContext(void) { return true; }
@@ -154,8 +249,9 @@ u32* Gfx_AllocImage(u32* offset, s32 w, s32 h) {
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);
+ color_offset[cur_fb], color_pitch, 0, 0,
+ offset, w * 4, 0, 0,
+ w, h, 4);
}
@@ -287,7 +383,26 @@ void Gfx_EndFrame(void) {
if (gfx_minFrameMs) LimitFPS();
}
-void Gfx_OnWindowResize(void) {/* TODO */
+void Gfx_OnWindowResize(void) {
+ f32 scale[4], offset[4];
+
+ u16 w = DisplayInfo.Width;
+ u16 h = DisplayInfo.Height;
+ f32 zmin = 0.0f;
+ f32 zmax = 1.0f;
+
+ scale[0] = w * 0.5f;
+ scale[1] = h * -0.5f;
+ scale[2] = (zmax - zmin) * 0.5f;
+ scale[3] = 0.0f;
+ offset[0] = w * 0.5f;
+ offset[1] = h * 0.5f;
+ offset[2] = (zmax + zmin) * 0.5f;
+ offset[3] = 0.0f;
+
+ rsxSetViewport(context, 0, 0, w, h, zmin, zmax, scale, offset);
+ rsxSetScissor(context, 0, 0, w, h);
+ /* TODO test */
}
@@ -309,13 +424,32 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
*#########################################################################################################################*/
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
- void* data = memalign(16, count * strideSizes[fmt]);
+ void* data = rsxMemalign(128, 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_BindVb(GfxResourceID vb) {
+ u32 offset;
+ rsxAddressToOffset(vb, &offset);
+ gfx_vertices = vb;
+
+ if (gfx_format == VERTEX_FORMAT_TEXTURED) {
+ rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_POS, 0, offset,
+ SIZEOF_VERTEX_TEXTURED, 3, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
+ rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_COLOR0, 0, offset + 12,
+ SIZEOF_VERTEX_TEXTURED, 4, GCM_VERTEX_DATA_TYPE_U8, GCM_LOCATION_RSX);
+ rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_TEX0, 0, offset + 16,
+ SIZEOF_VERTEX_TEXTURED, 2, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
+ } else {
+ rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_POS, 0, offset,
+ SIZEOF_VERTEX_COLOURED, 3, GCM_VERTEX_DATA_TYPE_F32, GCM_LOCATION_RSX);
+ rsxBindVertexArrayAttrib(context, GCM_VERTEX_ATTRIB_COLOR0, 0, offset + 12,
+ SIZEOF_VERTEX_COLOURED, 4, GCM_VERTEX_DATA_TYPE_U8, GCM_LOCATION_RSX);
+ }
+ VP_SwitchActive();
+ FP_SwitchActive();
+}
void Gfx_DeleteVb(GfxResourceID* vb) {
GfxResourceID data = *vb;/* TODO */
@@ -324,37 +458,36 @@ void Gfx_DeleteVb(GfxResourceID* vb) {
}
void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
- vb_size = count * strideSizes[fmt];/* TODO */
+ vb_size = count * strideSizes[fmt];
return vb;
}
void Gfx_UnlockVb(GfxResourceID vb) {
- gfx_vertices = vb;/* TODO */
- //sceKernelDcacheWritebackInvalidateRange(vb, vb_size);
+ Gfx_BindVb(vb);
+ rsxInvalidateVertexCache(context); // TODO needed?
}
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
- void* data = memalign(16, maxVertices * strideSizes[fmt]);
+ void* data = rsxMemalign(128, 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");
+ return data;
}
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
vb_size = count * strideSizes[fmt];
- return vb; /* TODO */
+ return vb;
}
-void Gfx_UnlockDynamicVb(GfxResourceID vb) {
- gfx_vertices = vb; /* TODO */
- //dcache_flush_range(vb, vb_size);
+void Gfx_UnlockDynamicVb(GfxResourceID vb) {
+ Gfx_BindVb(vb);
+ rsxInvalidateVertexCache(context); // TODO needed?
}
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);
+ Gfx_BindVb(vb);
+ rsxInvalidateVertexCache(context); // TODO needed?
}
@@ -377,6 +510,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
}
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
+ rsxInvalidateTextureCache(context, GCM_INVALIDATE_TEXTURE);
/* TODO */
}
@@ -411,16 +545,27 @@ void Gfx_SetFogMode(FogFunc func) {/* TODO */
/*########################################################################################################################*
*---------------------------------------------------------Matrices--------------------------------------------------------*
*#########################################################################################################################*/
+static struct Matrix _view, _proj;
void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {
-/* TODO */
+ struct Matrix* dst = type == MATRIX_PROJECTION ? &_proj : &_view;
+ *dst = *matrix;
+
+ struct Matrix mvp;
+ Matrix_Mul(&mvp, &_view, &_proj);
+
+ // TODO: dity uniforms
+ for (int i = 0; i < Array_Elems(VP_list); i++)
+ {
+ VertexProgram* vp = &VP_list[i];
+ rsxSetVertexProgramParameter(context, vp->prog, vp->mvp, (float*)&mvp);
+ }
}
void Gfx_LoadIdentityMatrix(MatrixType type) {
Gfx_LoadMatrix(type, &Matrix_Identity);
}
-
void Gfx_EnableTextureOffset(float x, float y) {
/* TODO */
}
@@ -437,15 +582,21 @@ void Gfx_SetVertexFormat(VertexFormat fmt) {
if (fmt == gfx_format) return;
gfx_format = fmt;
gfx_stride = strideSizes[fmt];/* TODO */
+
+ VP_SwitchActive();
+ FP_SwitchActive();
}
void Gfx_DrawVb_Lines(int verticesCount) {/* TODO */
+ rsxDrawVertexArray(context, GCM_TYPE_LINES, 0, verticesCount);
}
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {/* TODO */
+ rsxDrawVertexArray(context, GCM_TYPE_QUADS, startVertex, verticesCount);
}
void Gfx_DrawVb_IndexedTris(int verticesCount) {/* TODO */
+ rsxDrawVertexArray(context, GCM_TYPE_QUADS, 0, verticesCount);
}
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {/* TODO */
diff --git a/src/Makefile_PS3 b/src/Makefile_PS3
index 9c5b27a1a..73b58bc98 100644
--- a/src/Makefile_PS3
+++ b/src/Makefile_PS3
@@ -19,6 +19,7 @@ TARGET := ClassiCube-PS3
BUILD := build-ps3
SOURCES := src
INCLUDES :=
+SHADERS := misc/ps3
TITLE := ClassiCube
APPID := CUBE00200
@@ -27,7 +28,7 @@ CONTENTID := UP0001-$(APPID)_00-0000000000000000
# options for code generation
#---------------------------------------------------------------------------------
-CFLAGS = -O2 -DPLAT_PS3 -Wall -mcpu=cell $(MACHDEP) $(INCLUDE)
+CFLAGS = -O2 -DPLAT_PS3 -Wall -mcpu=cell -fno-math-errno $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
@@ -52,7 +53,8 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export OUTPUT := $(CURDIR)/$(TARGET)
-export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(SHADERS),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
@@ -64,13 +66,20 @@ export BUILDDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
+VCGFILES := $(notdir $(wildcard misc/ps3/*.vcg))
+FCGFILES := $(notdir $(wildcard misc/ps3/*.fcg))
+
+VPOFILES := $(VCGFILES:.vcg=.vpo)
+FPOFILES := $(FCGFILES:.fcg=.fpo)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
export LD := $(CC)
-export OFILES := $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
-
+export OFILES := $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o) \
+ $(addsuffix .o,$(VPOFILES)) \
+ $(addsuffix .o,$(FPOFILES))
+
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
@@ -111,9 +120,15 @@ $(OUTPUT).elf: $(OFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .bin extension
-#---------------------------------------------------------------------------------
-%.bin.o : %.bin
-#---------------------------------------------------------------------------------
+%.bin.o : %.bin
+ @echo $(notdir $<)
+ @$(bin2o)
+
+%.vpo.o : %.vpo
+ @echo $(notdir $<)
+ @$(bin2o)
+
+%.fpo.o : %.fpo
@echo $(notdir $<)
@$(bin2o)
diff --git a/src/Platform_PS3.c b/src/Platform_PS3.c
index a37f755ec..416c16580 100644
--- a/src/Platform_PS3.c
+++ b/src/Platform_PS3.c
@@ -21,14 +21,13 @@
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -98,19 +97,26 @@ cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
/*########################################################################################################################*
*-----------------------------------------------------Directory/File------------------------------------------------------*
*#########################################################################################################################*/
+static const cc_string root_path = String_FromConst("/dev_hdd0/ClassiCube/");
+static void GetNativePath(char* str, const cc_string* path) {
+ Mem_Copy(str, root_path.buffer, root_path.length);
+ str += root_path.length;
+ String_EncodeUtf8(str, path);
+}
+
cc_result Directory_Create(const cc_string* path) {
char str[NATIVE_STR_LEN];
- String_EncodeUtf8(str, path);
+ GetNativePath(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;
+ return sysLv2FsMkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
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);
+ sysFSStat sb;
+ GetNativePath(str, path);
+ return sysLv2FsStat(str, &sb) == 0 && S_ISREG(sb.st_mode);
}
cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) {
@@ -121,7 +127,7 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall
char* src;
int len, res, is_dir;
- String_EncodeUtf8(str, dirPath);
+ GetNativePath(str, dirPath);
dirPtr = opendir(str);
if (!dirPtr) return errno;
@@ -142,17 +148,8 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall
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);
@@ -170,7 +167,7 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall
static cc_result File_Do(cc_file* file, const cc_string* path, int mode) {
char str[NATIVE_STR_LEN];
- String_EncodeUtf8(str, path);
+ GetNativePath(str, path);
*file = open(str, mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
return *file == -1 ? errno : 0;
}
@@ -196,7 +193,7 @@ cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32*
}
cc_result File_Close(cc_file file) {
- return close(file) == -1 ? errno : 0;
+ return sysLv2FsClose(file);
}
cc_result File_Seek(cc_file file, int offset, int seekType) {
@@ -210,9 +207,14 @@ cc_result File_Position(cc_file file, cc_uint32* pos) {
}
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;
+ sysFSStat st;
+ int res = sysLv2FsFStat(file, &st);
+
+ if (res) {
+ *len = -1; return res;
+ } else {
+ *len = st.st_size; return 0;
+ }
}
@@ -445,6 +447,8 @@ cc_result Process_StartOpen(const cc_string* args) {
void Platform_Init(void) {
netInitialize();
+ // Create root directory
+ Directory_Create(&String_Empty);
}
void Platform_Free(void) { }
diff --git a/src/Window_PS3.c b/src/Window_PS3.c
index 36f353f20..0e79149dc 100644
--- a/src/Window_PS3.c
+++ b/src/Window_PS3.c
@@ -75,6 +75,7 @@ void Window_Close(void) {
*----------------------------------------------------Input processing-----------------------------------------------------*
*#########################################################################################################################*/
static void HandleButtons(padData* data) {
+ //Platform_Log2("BUTTONS: %h (%h)", &data->button[2], &data->button[0]);
Input_SetNonRepeatable(CCPAD_A, data->BTN_TRIANGLE);
Input_SetNonRepeatable(CCPAD_B, data->BTN_SQUARE);
Input_SetNonRepeatable(CCPAD_X, data->BTN_CROSS);
@@ -129,18 +130,17 @@ void Window_AllocFramebuffer(struct Bitmap* bmp) {
u32* pixels = Gfx_AllocImage(&fb_offset, bmp->width, bmp->height);
bmp->scan0 = pixels;
fb_bmp = *bmp;
+
+ Gfx_ClearCol(PackedCol_Make(0x40, 0x60, 0x80, 0xFF));
}
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();
+ // TODO: Only transfer dirty region instead of the entire bitmap
Gfx_TransferImage(fb_offset, fb_bmp.width, fb_bmp.height);
Gfx_EndFrame();
- Platform_LogConst("FRAME END");
}
void Window_FreeFramebuffer(struct Bitmap* bmp) {