diff --git a/src/display/pspdisplay.h b/src/display/pspdisplay.h index c72ca31d..2e31f08e 100644 --- a/src/display/pspdisplay.h +++ b/src/display/pspdisplay.h @@ -31,12 +31,15 @@ enum PspDisplayPixelFormats { }; enum PspDisplaySetBufSync { - /** Buffer change effective immediately */ - PSP_DISPLAY_SETBUF_IMMEDIATE = 0, - /** Buffer change effective next frame */ - PSP_DISPLAY_SETBUF_NEXTFRAME = 1 + /** Buffer change effective next hsync */ + PSP_DISPLAY_SETBUF_NEXTHSYNC = 0, + /** Buffer change effective next vsync */ + PSP_DISPLAY_SETBUF_NEXTVSYNC = 1 }; +/** Values for retro compatibility */ +#define PSP_DISPLAY_SETBUF_IMMEDIATE PSP_DISPLAY_SETBUF_NEXTHSYNC +#define PSP_DISPLAY_SETBUF_NEXTFRAME PSP_DISPLAY_SETBUF_NEXTVSYNC enum PspDisplayErrorCodes { diff --git a/src/gu/Makefile.am b/src/gu/Makefile.am index c0cb0145..1a44d0cb 100644 --- a/src/gu/Makefile.am +++ b/src/gu/Makefile.am @@ -57,6 +57,7 @@ libpspgu_a_SOURCES = \ sceGuEnable.c \ sceGuEndObject.c \ sceGuFinish.c \ + sceGuFinishId.c \ sceGuFog.c \ sceGuFrontFace.c \ sceGuGetAllStatus.c \ diff --git a/src/gu/guInternal.h b/src/gu/guInternal.h index 8c3b5eb2..0b214dd9 100644 --- a/src/gu/guInternal.h +++ b/src/gu/guInternal.h @@ -116,7 +116,7 @@ extern GuLightSettings light_settings[4]; void callbackSig(int id, void *arg); void callbackFin(int id, void *arg); -void resetValues(); +void _sceGuResetGlobalVariables(); typedef enum GECommand { @@ -645,12 +645,18 @@ static inline void sendCommandf(GECommand cmd, float argument) sendCommandi(cmd, t.i >> 8); } -static inline void sendCommandiStall(GECommand cmd, int argument) -{ - sendCommandi(cmd, argument); - - if (!gu_object_stack_depth && !gu_curr_context) - sceGeListUpdateStallAddr(ge_list_executed[0], gu_list->current); +static inline int _sceGuUpdateStallAddr(void) { + if (gu_curr_context == GU_DIRECT) { + // Just if there are no objects in the stack (no guBeginObject) + if (!gu_object_stack_depth) { + int res; + res = sceGeListUpdateStallAddr(ge_list_executed[0], gu_list->current); + if (res < 0) { + return res; + } + } + } + return 0; } #endif diff --git a/src/gu/pspgu.h b/src/gu/pspgu.h index c5f246fb..bd185dfc 100644 --- a/src/gu/pspgu.h +++ b/src/gu/pspgu.h @@ -433,8 +433,10 @@ void sceGuFog(float near, float far, unsigned int color); * Initalize the GU system * * This function MUST be called as the first function, otherwise state is undetermined. + * + * @return 0 for success, < 0 for failure **/ -void sceGuInit(void); +int sceGuInit(void); /** * Shutdown the GU system @@ -475,6 +477,11 @@ void* sceGuSetCallback(int signal, void (*callback)(int)); /** * Trigger signal to call code from the command stream + * + * Available signals are: + * - GU_SIGNAL_WAIT - Wait for callback to finish + * - GU_SIGNAL_NOWAIT - Do not wait for callback to finish + * - GU_SIGNAL_PAUSE - Pause execution until callback is finished * * Available behaviors are: * - GU_BEHAVIOR_SUSPEND - Stops display list execution until callback function finished @@ -564,8 +571,9 @@ int sceGuFinishId(unsigned int id); * Call previously generated display-list * * @param list - Display list to call + * @return 0 for success, < 0 for failure **/ -void sceGuCallList(const void* list); +int sceGuCallList(const void* list); /** * Set wether to use stack-based calls or signals to handle execution of called lists. @@ -1525,8 +1533,8 @@ void sceGuDrawArrayN(int primitive_type, int vertex_type, int vcount, int primco * Set how the display should be set * * Available behaviours are: - * - PSP_DISPLAY_SETBUF_IMMEDIATE - Display is swapped immediately - * - PSP_DISPLAY_SETBUF_NEXTFRAME - Display is swapped on the next frame + * - PSP_DISPLAY_SETBUF_NEXTHSYNC - Display is swapped on the next hsync + * - PSP_DISPLAY_SETBUF_NEXTVSYNC - Display is swapped on the next vsync * * Do remember that this swaps the pointers internally, regardless of setting, so be careful to wait until the next * vertical blank or use another buffering algorithm (see guSwapBuffersCallback()). diff --git a/src/gu/resetValues.c b/src/gu/resetValues.c index 2b039533..4fed2744 100644 --- a/src/gu/resetValues.c +++ b/src/gu/resetValues.c @@ -8,7 +8,7 @@ #include "guInternal.h" -void resetValues() +void _sceGuResetGlobalVariables() { unsigned int i; @@ -18,7 +18,7 @@ void resetValues() gu_current_frame = 0; gu_object_stack_depth = 0; - gu_display_on = 0; + gu_display_on = GU_FALSE; gu_call_mode = GU_CALL_NORMAL; gu_draw_buffer.pixel_size = 1; diff --git a/src/gu/sceGuCallList.c b/src/gu/sceGuCallList.c index d59043ad..20a4bb0c 100644 --- a/src/gu/sceGuCallList.c +++ b/src/gu/sceGuCallList.c @@ -8,19 +8,25 @@ #include "guInternal.h" -void sceGuCallList(const void *list) +int sceGuCallList(const void *list) { + int res; unsigned int list_addr = (unsigned int)list; if (gu_call_mode == GU_CALL_SIGNAL) { sendCommandi(SIGNAL, (list_addr >> 16) | 0x110000); sendCommandi(END, list_addr & 0xffff); - sendCommandiStall(NOP, 0); } else { sendCommandi(BASE, (list_addr >> 8) & 0xf0000); - sendCommandiStall(CALL, list_addr); + sendCommandi(CALL, list_addr); } + + res = _sceGuUpdateStallAddr(); + if (res < 0) { + return res; + } + return 0; } diff --git a/src/gu/sceGuColor.c b/src/gu/sceGuColor.c index 4ccc4549..946bd39e 100644 --- a/src/gu/sceGuColor.c +++ b/src/gu/sceGuColor.c @@ -10,5 +10,5 @@ void sceGuColor(unsigned int color) { - sceGuMaterial(7,color); + sceGuMaterial(GU_AMBIENT | GU_DIFFUSE | GU_SPECULAR, color); } diff --git a/src/gu/sceGuDisable.c b/src/gu/sceGuDisable.c index 461fbf5b..8b05eaad 100644 --- a/src/gu/sceGuDisable.c +++ b/src/gu/sceGuDisable.c @@ -89,6 +89,6 @@ void sceGuDisable(int state) break; } - if (state < 22) + if (state < GU_MAX_STATUS) gu_states &= ~(1 << state); } diff --git a/src/gu/sceGuDispBuffer.c b/src/gu/sceGuDispBuffer.c index 0436522e..807c1d41 100644 --- a/src/gu/sceGuDispBuffer.c +++ b/src/gu/sceGuDispBuffer.c @@ -30,5 +30,5 @@ void sceGuDispBuffer(int width, int height, void *dispbp, int dispbw) sceDisplaySetMode(0, gu_draw_buffer.width, gu_draw_buffer.height); if (gu_display_on) - sceDisplaySetFrameBuf((void *)(((unsigned int)ge_edram_address) + ((unsigned int)gu_draw_buffer.disp_buffer)), dispbw, gu_draw_buffer.pixel_size, PSP_DISPLAY_SETBUF_NEXTFRAME); + sceDisplaySetFrameBuf((void *)(((unsigned int)ge_edram_address) + ((unsigned int)gu_draw_buffer.disp_buffer)), dispbw, gu_draw_buffer.pixel_size, PSP_DISPLAY_SETBUF_NEXTVSYNC); } diff --git a/src/gu/sceGuDisplay.c b/src/gu/sceGuDisplay.c index 6006c524..90987c4e 100644 --- a/src/gu/sceGuDisplay.c +++ b/src/gu/sceGuDisplay.c @@ -13,10 +13,10 @@ int sceGuDisplay(int state) { - if (state) - sceDisplaySetFrameBuf((void*)((unsigned int)ge_edram_address+(unsigned int)gu_draw_buffer.disp_buffer),gu_draw_buffer.frame_width,gu_draw_buffer.pixel_size,PSP_DISPLAY_SETBUF_NEXTFRAME); + if (state == GU_TRUE) + sceDisplaySetFrameBuf((void *)((unsigned int)ge_edram_address + (unsigned int)gu_draw_buffer.disp_buffer), gu_draw_buffer.frame_width, gu_draw_buffer.pixel_size, PSP_DISPLAY_SETBUF_NEXTVSYNC); else - sceDisplaySetFrameBuf(0,0,0,PSP_DISPLAY_SETBUF_NEXTFRAME); + sceDisplaySetFrameBuf(NULL, 0, 0, PSP_DISPLAY_SETBUF_NEXTVSYNC); gu_display_on = state; return state; diff --git a/src/gu/sceGuDrawArray.c b/src/gu/sceGuDrawArray.c index c98143c9..2dcdb872 100644 --- a/src/gu/sceGuDrawArray.c +++ b/src/gu/sceGuDrawArray.c @@ -25,5 +25,6 @@ void sceGuDrawArray(int prim, int vtype, int count, const void *indices, const v sendCommandi(VADDR, ((unsigned int)vertices)); } - sendCommandiStall(PRIM, (prim << 16) | count); + sendCommandi(PRIM, (prim << 16) | count); + _sceGuUpdateStallAddr(); } diff --git a/src/gu/sceGuDrawArrayN.c b/src/gu/sceGuDrawArrayN.c index 7bf743f5..dd5ecc45 100644 --- a/src/gu/sceGuDrawArrayN.c +++ b/src/gu/sceGuDrawArrayN.c @@ -30,7 +30,7 @@ void sceGuDrawArrayN(int primitive_type, int vertex_type, int vcount, int primco int i; for (i = 0; i < primcount; i++) sendCommandi(PRIM, (primitive_type << 16) | vcount); - - sendCommandiStall(PRIM, (primitive_type << 16) | vcount); } + + _sceGuUpdateStallAddr(); } diff --git a/src/gu/sceGuEnable.c b/src/gu/sceGuEnable.c index ad6d38de..770752b3 100644 --- a/src/gu/sceGuEnable.c +++ b/src/gu/sceGuEnable.c @@ -89,6 +89,6 @@ void sceGuEnable(int state) break; } - if (state < 22) + if (state < GU_MAX_STATUS) gu_states |= (1 << state); } diff --git a/src/gu/sceGuFinish.c b/src/gu/sceGuFinish.c index 9f68aadd..ad03b7f1 100644 --- a/src/gu/sceGuFinish.c +++ b/src/gu/sceGuFinish.c @@ -8,42 +8,6 @@ #include "guInternal.h" -int sceGuFinishId(unsigned int id) -{ - switch (gu_curr_context) - { - case GU_DIRECT: - case GU_SEND: - { - sendCommandi(FINISH, id & 0xffff); - sendCommandiStall(END, 0); - } - break; - - case GU_CALL: - { - if (gu_call_mode == GU_CALL_SIGNAL) - { - sendCommandi(SIGNAL, 0x120000); - sendCommandi(END, 0); - sendCommandiStall(NOP, 0); - } - else - { - sendCommandi(RET, 0); - } - } - break; - } - - unsigned int size = ((unsigned int)gu_list->current) - ((unsigned int)gu_list->start); - - // go to parent list - gu_curr_context = gu_list->parent_context; - gu_list = &gu_contexts[gu_curr_context].list; - return size; -} - int sceGuFinish(void) { return sceGuFinishId(0); diff --git a/src/gu/sceGuFinishId.c b/src/gu/sceGuFinishId.c new file mode 100644 index 00000000..ad5e638f --- /dev/null +++ b/src/gu/sceGuFinishId.c @@ -0,0 +1,56 @@ +/* + * PSP Software Development Kit - https://github.com/pspdev + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * Copyright (c) 2005 Jesper Svennevid + */ + +#include "guInternal.h" +#include +#include + +int sceGuFinishId(unsigned int id) +{ + int ret; + int intr; + + switch (gu_curr_context) + { + case GU_DIRECT: + sendCommandi(FINISH, id & 0xffff); + sendCommandi(END, 0); + ret = _sceGuUpdateStallAddr(); + if (ret < 0) + { + return ret; + } + break; + case GU_SEND: + sendCommandi(FINISH, id & 0xffff); + sendCommandi(END, 0); + break; + case GU_CALL: + if (gu_call_mode == GU_CALL_SIGNAL) + { + sendCommandi(SIGNAL, 0x120000); + sendCommandi(END, 0); + } + else + { + sendCommandi(RET, 0); + } + break; + default: + return SCE_DISPLAY_ERROR_ARGUMENT; + } + + unsigned int size = ((unsigned int)gu_list->current) - ((unsigned int)gu_list->start); + + // go to parent list + intr = sceKernelCpuSuspendIntr(); + gu_curr_context = gu_list->parent_context; + gu_list = &gu_contexts[gu_curr_context].list; + sceKernelCpuResumeIntr(intr); + return size; +} \ No newline at end of file diff --git a/src/gu/sceGuInit.c b/src/gu/sceGuInit.c index 46a428f8..8a51ae80 100644 --- a/src/gu/sceGuInit.c +++ b/src/gu/sceGuInit.c @@ -235,46 +235,70 @@ static unsigned int __attribute__((aligned(16))) ge_init_list[] = ZV(END), }; -void callbackFin(int id, void* arg) +void callbackFin(int id, void *arg) { - GuSettings* settings = (GuSettings*)arg; + GuSettings *settings = (GuSettings *)arg; if (settings->fin) settings->fin(id & 0xffff); } -void callbackSig(int id, void* arg) +void callbackSig(int id, void *arg) { - GuSettings* settings = (GuSettings*)arg; + GuSettings *settings = (GuSettings *)arg; settings->signal_history[(settings->signal_offset++) & 15] = id & 0xffff; if (settings->sig) settings->sig(id & 0xffff); - sceKernelSetEventFlag(settings->kernel_event_flag,1); + sceKernelSetEventFlag(settings->kernel_event_flag, 1); } -void sceGuInit(void) +int sceGuInit(void) { + int res; PspGeCallbackData callback; + + ge_edram_address = sceGeEdramGetAddr(); + _sceGuResetGlobalVariables(); + + res = sceKernelCreateEventFlag("SceGuSignal", PSP_EVENT_WAITMULTIPLE, 3, 0); + if (res < 0) + { + return res; + } + gu_settings.kernel_event_flag = res; + callback.signal_func = callbackSig; callback.signal_arg = &gu_settings; callback.finish_func = callbackFin; callback.finish_arg = &gu_settings; - gu_settings.ge_callback_id = sceGeSetCallback(&callback); - - gu_settings.swapBuffersCallback = 0; - gu_settings.swapBuffersBehaviour = PSP_DISPLAY_SETBUF_IMMEDIATE; - - ge_edram_address = sceGeEdramGetAddr(); + res = sceGeSetCallback(&callback); + if (res < 0) + { + sceKernelDeleteEventFlag(gu_settings.kernel_event_flag); + gu_settings.kernel_event_flag = -1; + return res; + } + gu_settings.ge_callback_id = res; // initialize graphics hardware - ge_list_executed[0] = sceGeListEnQueue((void *)((unsigned int)ge_init_list & 0x1fffffff), 0, gu_settings.ge_callback_id, 0); - - resetValues(); - - gu_settings.kernel_event_flag = sceKernelCreateEventFlag("SceGuSignal", 512, 3, 0); - + res = sceGeListEnQueue((void *)((unsigned int)ge_init_list & 0x1fffffff), NULL, gu_settings.ge_callback_id, NULL); + if (res < 0) + { + sceKernelDeleteEventFlag(gu_settings.kernel_event_flag); + sceGeUnsetCallback(gu_settings.ge_callback_id); + gu_settings.ge_callback_id = -1; + gu_settings.kernel_event_flag = -1; + return res; + } + ge_list_executed[0] = res; // wait for init to complete sceGeListSync(ge_list_executed[0], 0); + sceGeDrawSync(0); + + gu_settings.swapBuffersCallback = NULL; + gu_settings.swapBuffersBehaviour = PSP_DISPLAY_SETBUF_NEXTHSYNC; + + return 0; } diff --git a/src/gu/sceGuSendList.c b/src/gu/sceGuSendList.c index 41ad460e..71b781b5 100644 --- a/src/gu/sceGuSendList.c +++ b/src/gu/sceGuSendList.c @@ -13,15 +13,18 @@ int sceGuSendList(int mode, const void *list, PspGeContext *context) { - gu_settings.signal_offset = 0; - - // TODO: figure out this structure PspGeListArgs args; - args.size = 8; // Size of structure? - args.context = context; + int list_id; + int callback; - int list_id = 0; - int callback = gu_settings.ge_callback_id; + args.size = sizeof(PspGeListArgs); + args.context = context; + args.numStacks = 0; + args.stacks = NULL; + + callback = gu_settings.ge_callback_id; + gu_settings.signal_offset = 0; + list_id = -1; switch (mode) { diff --git a/src/gu/sceGuSetCallback.c b/src/gu/sceGuSetCallback.c index e101a46e..e75607ab 100644 --- a/src/gu/sceGuSetCallback.c +++ b/src/gu/sceGuSetCallback.c @@ -8,24 +8,19 @@ #include "guInternal.h" -void* sceGuSetCallback(int signal, GuCallback callback) +void *sceGuSetCallback(int signal, GuCallback callback) { - GuCallback old_callback = 0; + GuCallback old_callback = NULL; switch (signal) { - case GU_CALLBACK_SIGNAL: - { - old_callback = gu_settings.sig; - gu_settings.sig = callback; - } + case GU_CALLBACK_SIGNAL: + old_callback = gu_settings.sig; + gu_settings.sig = callback; break; - - case GU_CALLBACK_FINISH: - { - old_callback = gu_settings.fin; - gu_settings.fin = callback; - } + case GU_CALLBACK_FINISH: + old_callback = gu_settings.fin; + gu_settings.fin = callback; break; } diff --git a/src/gu/sceGuShadeModel.c b/src/gu/sceGuShadeModel.c index 35808603..faef3007 100644 --- a/src/gu/sceGuShadeModel.c +++ b/src/gu/sceGuShadeModel.c @@ -10,5 +10,5 @@ void sceGuShadeModel(int mode) { - sendCommandi(SHADE_MODE, mode ? 1 : 0); + sendCommandi(SHADE_MODE, mode); } diff --git a/src/gu/sceGuSignal.c b/src/gu/sceGuSignal.c index c1779c16..df691cc0 100644 --- a/src/gu/sceGuSignal.c +++ b/src/gu/sceGuSignal.c @@ -13,11 +13,11 @@ void sceGuSignal(int signal, int argument) sendCommandi(SIGNAL, ((signal & 0xff) << 16) | (argument & 0xffff)); sendCommandi(END, 0); - if (GU_SIGNAL_PAUSE == 3) + if (signal == GU_SIGNAL_PAUSE) { sendCommandi(FINISH, 0); sendCommandi(END, 0); } - sendCommandiStall(NOP, 0); -} + _sceGuUpdateStallAddr(); +} \ No newline at end of file diff --git a/src/gu/sceGuStart.c b/src/gu/sceGuStart.c index ef14da39..96791e9a 100644 --- a/src/gu/sceGuStart.c +++ b/src/gu/sceGuStart.c @@ -10,12 +10,16 @@ #include #include +#include void sceGuStart(int ctype, void *list) { + int intr; GuContext *context = &gu_contexts[ctype]; unsigned int *local_list = (unsigned int *)(((unsigned int)list) | 0x40000000); + intr = sceKernelCpuSuspendIntr(); + // setup display list context->list.start = local_list; @@ -26,10 +30,11 @@ void sceGuStart(int ctype, void *list) // store current context gu_curr_context = ctype; + sceKernelCpuResumeIntr(intr); if (ctype == GU_DIRECT) { - ge_list_executed[0] = sceGeListEnQueue(local_list, local_list, gu_settings.ge_callback_id, 0); + ge_list_executed[0] = sceGeListEnQueue(local_list, local_list, gu_settings.ge_callback_id, NULL); gu_settings.signal_offset = 0; } diff --git a/src/gu/sceGuSync.c b/src/gu/sceGuSync.c index ffd77acd..d23a753f 100644 --- a/src/gu/sceGuSync.c +++ b/src/gu/sceGuSync.c @@ -15,9 +15,15 @@ int sceGuSync(int mode, int what) { switch (mode) { - case GU_SYNC_FINISH: return sceGeDrawSync(what); - case GU_SYNC_LIST: return sceGeListSync(ge_list_executed[0],what); - case GU_SYNC_SEND: return sceGeListSync(ge_list_executed[1],what); - default: case GU_SYNC_SIGNAL: case GU_SYNC_DONE: return 0; + case GU_SYNC_FINISH: + return sceGeDrawSync(what); + case GU_SYNC_LIST: + return sceGeListSync(ge_list_executed[0], what); + case GU_SYNC_SEND: + return sceGeListSync(ge_list_executed[1], what); + default: + case GU_SYNC_SIGNAL: + case GU_SYNC_DONE: + return 0; } } diff --git a/src/samples/prx/image_display/main.c b/src/samples/prx/image_display/main.c index 82aedf6b..260bfe3b 100644 --- a/src/samples/prx/image_display/main.c +++ b/src/samples/prx/image_display/main.c @@ -129,8 +129,8 @@ int main_thread(SceSize args, void *argp){ // get vram - int ret = sceDisplayGetFrameBuf((void*)&vram32, &bufferwidth, &pixelformat, PSP_DISPLAY_SETBUF_IMMEDIATE); - // works with both PSP_DISPLAY_SETBUF_NEXTFRAME and PSP_DISPLAY_SETBUF_IMMEDIATE + int ret = sceDisplayGetFrameBuf((void*)&vram32, &bufferwidth, &pixelformat, PSP_DISPLAY_SETBUF_NEXTHSYNC); + // works with both PSP_DISPLAY_SETBUF_NEXTVSYNC and PSP_DISPLAY_SETBUF_NEXTHSYNC // check if return value from sceDisplayGetFrameBuf is valid // check if vram32 is not NULL diff --git a/src/user/pspthreadman.h b/src/user/pspthreadman.h index 8fe7b350..60ff9126 100644 --- a/src/user/pspthreadman.h +++ b/src/user/pspthreadman.h @@ -690,6 +690,8 @@ typedef struct SceKernelEventFlagOptParam SceKernelEventFlagOptParam; /** Event flag creation attributes */ enum PspEventFlagAttributes { + /** Allow the event flag to be waited upon by a single thread */ + PSP_EVENT_WAITSINGLE = 0x00, /** Allow the event flag to be waited upon by multiple threads */ PSP_EVENT_WAITMULTIPLE = 0x200 };