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) {