diff options
Diffstat (limited to 'source/psp/gui.c')
-rw-r--r-- | source/psp/gui.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/source/psp/gui.c b/source/psp/gui.c new file mode 100644 index 0000000..c135cb4 --- /dev/null +++ b/source/psp/gui.c @@ -0,0 +1,293 @@ +/* gameplaySP + * + * Copyright (C) 2006 Exophase <exophase@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include "font.h" + +#include <pspctrl.h> + +#include <pspkernel.h> +#include <pspdebug.h> +#include <pspdisplay.h> + +#include <pspgu.h> +#include <psppower.h> +#include <psprtc.h> + +static float *screen_vertex = (float *)0x441FC100; +static u32 *ge_cmd = (u32 *)0x441FC000; +static u16 *psp_gu_vram_base = (u16 *)(0x44000000); +static u32 *ge_cmd_ptr = (u32 *)0x441FC000; +static u32 gecbid; +static u32 video_direct = 0; + +static u32 __attribute__((aligned(16))) display_list[32]; + +#define GBA_SCREEN_WIDTH 240 +#define GBA_SCREEN_HEIGHT 160 + +#define PSP_SCREEN_WIDTH 480 +#define PSP_SCREEN_HEIGHT 272 +#define PSP_LINE_SIZE 512 + +#define PSP_ALL_BUTTON_MASK 0xFFFF + +#define GE_CMD_FBP 0x9C +#define GE_CMD_FBW 0x9D +#define GE_CMD_TBP0 0xA0 +#define GE_CMD_TBW0 0xA8 +#define GE_CMD_TSIZE0 0xB8 +#define GE_CMD_TFLUSH 0xCB +#define GE_CMD_CLEAR 0xD3 +#define GE_CMD_VTYPE 0x12 +#define GE_CMD_BASE 0x10 +#define GE_CMD_VADDR 0x01 +#define GE_CMD_IADDR 0x02 +#define GE_CMD_PRIM 0x04 +#define GE_CMD_FINISH 0x0F +#define GE_CMD_SIGNAL 0x0C +#define GE_CMD_NOP 0x00 + +#define GE_CMD(cmd, operand) \ + *ge_cmd_ptr = (((GE_CMD_##cmd) << 24) | (operand)); \ + ge_cmd_ptr++ \ + +static u16 *screen_texture = (u16 *)(0x4000000 + (512 * 272 * 2)); +static u16 *current_screen_texture = (u16 *)(0x4000000 + (512 * 272 * 2)); +static u16 *GBAScreen = (u16 *)(0x4000000 + (512 * 272 * 2)); +static u32 GBAScreenPitch = 240; + +static void Ge_Finish_Callback(int id, void *arg) +{ +} + +void init_video() +{ + sceDisplaySetMode(0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + + sceDisplayWaitVblankStart(); + sceDisplaySetFrameBuf((void*)psp_gu_vram_base, PSP_LINE_SIZE, + PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); + + sceGuInit(); + + sceGuStart(GU_DIRECT, display_list); + sceGuDrawBuffer(GU_PSM_5650, (void*)0, PSP_LINE_SIZE); + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, + (void*)0, PSP_LINE_SIZE); + sceGuClear(GU_COLOR_BUFFER_BIT); + + sceGuOffset(2048 - (PSP_SCREEN_WIDTH / 2), 2048 - (PSP_SCREEN_HEIGHT / 2)); + sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + + sceGuScissor(0, 0, PSP_SCREEN_WIDTH + 1, PSP_SCREEN_HEIGHT + 1); + sceGuEnable(GU_SCISSOR_TEST); + sceGuTexMode(GU_PSM_5650, 0, 0, GU_FALSE); + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); + sceGuTexFilter(GU_LINEAR, GU_LINEAR); + sceGuEnable(GU_TEXTURE_2D); + + sceGuFrontFace(GU_CW); + sceGuDisable(GU_BLEND); + + sceGuFinish(); + sceGuSync(0, 0); + + sceDisplayWaitVblankStart(); + sceGuDisplay(GU_TRUE); + + PspGeCallbackData gecb; + gecb.signal_func = NULL; + gecb.signal_arg = NULL; + gecb.finish_func = Ge_Finish_Callback; + gecb.finish_arg = NULL; + gecbid = sceGeSetCallback(&gecb); + + screen_vertex[0] = 0 + 0.5; + screen_vertex[1] = 0 + 0.5; + screen_vertex[2] = 0 + 0.5; + screen_vertex[3] = 0 + 0.5; + screen_vertex[4] = 0; + screen_vertex[5] = GBA_SCREEN_WIDTH - 0.5; + screen_vertex[6] = GBA_SCREEN_HEIGHT - 0.5; + screen_vertex[7] = PSP_SCREEN_WIDTH - 0.5; + screen_vertex[8] = PSP_SCREEN_HEIGHT - 0.5; + screen_vertex[9] = 0; + + // Set framebuffer to PSP VRAM + GE_CMD(FBP, ((u32)psp_gu_vram_base & 0x00FFFFFF)); + GE_CMD(FBW, (((u32)psp_gu_vram_base & 0xFF000000) >> 8) | PSP_LINE_SIZE); + // Set texture 0 to the screen texture + GE_CMD(TBP0, ((u32)screen_texture & 0x00FFFFFF)); + GE_CMD(TBW0, (((u32)screen_texture & 0xFF000000) >> 8) | GBA_SCREEN_WIDTH); + // Set the texture size to 256 by 256 (2^8 by 2^8) + GE_CMD(TSIZE0, (8 << 8) | 8); + // Flush the texture cache + GE_CMD(TFLUSH, 0); + // Use 2D coordinates, no indeces, no weights, 32bit float positions, + // 32bit float texture coordinates + GE_CMD(VTYPE, (1 << 23) | (0 << 11) | (0 << 9) | + (3 << 7) | (0 << 5) | (0 << 2) | 3); + // Set the base of the index list pointer to 0 + GE_CMD(BASE, 0); + // Set the rest of index list pointer to 0 (not being used) + GE_CMD(IADDR, 0); + // Set the base of the screen vertex list pointer + GE_CMD(BASE, ((u32)screen_vertex & 0xFF000000) >> 8); + // Set the rest of the screen vertex list pointer + GE_CMD(VADDR, ((u32)screen_vertex & 0x00FFFFFF)); + // Primitive kick: render sprite (primitive 6), 2 vertices + GE_CMD(PRIM, (6 << 16) | 2); + // Done with commands + GE_CMD(FINISH, 0); + // Raise signal interrupt + GE_CMD(SIGNAL, 0); + GE_CMD(NOP, 0); + GE_CMD(NOP, 0); +} + +u32 screen_flip = 0; + +void ReGBA_RenderScreen() +{ + if(video_direct == 0) + { + u32 *old_ge_cmd_ptr = ge_cmd_ptr; + sceKernelDcacheWritebackAll(); + + // Render the current screen + ge_cmd_ptr = ge_cmd + 2; + GE_CMD(TBP0, ((u32) GBAScreen & 0x00FFFFFF)); + GE_CMD(TBW0, (((u32) GBAScreen & 0xFF000000) >> 8) | + GBA_SCREEN_WIDTH); + ge_cmd_ptr = old_ge_cmd_ptr; + + sceGeListEnQueue(ge_cmd, ge_cmd_ptr, gecbid, NULL); + + // Flip to the next screen + screen_flip ^= 1; + + if(screen_flip) + GBAScreen = screen_texture + (240 * 160 * 2); + else + GBAScreen = screen_texture; + } +} + +void video_resolution_large() +{ + if(video_direct != 1) + { + video_direct = 1; + screen_pixels = psp_gu_vram_base; + screen_pitch = 512; + sceGuStart(GU_DIRECT, display_list); + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, + (void*)0, PSP_LINE_SIZE); + sceGuFinish(); + } +} + +void set_gba_resolution(video_scale_type scale) +{ + u32 filter_linear = 0; + screen_scale = scale; + switch(scale) + { + case unscaled: + screen_vertex[2] = 120 + 0.5; + screen_vertex[3] = 56 + 0.5; + screen_vertex[7] = GBA_SCREEN_WIDTH + 120 - 0.5; + screen_vertex[8] = GBA_SCREEN_HEIGHT + 56 - 0.5; + break; + + case scaled_aspect: + screen_vertex[2] = 36 + 0.5; + screen_vertex[3] = 0 + 0.5; + screen_vertex[7] = 408 + 36 - 0.5; + screen_vertex[8] = PSP_SCREEN_HEIGHT - 0.5; + break; + + case fullscreen: + screen_vertex[2] = 0; + screen_vertex[3] = 0; + screen_vertex[7] = PSP_SCREEN_WIDTH; + screen_vertex[8] = PSP_SCREEN_HEIGHT; + break; + } + + sceGuStart(GU_DIRECT, display_list); + if(screen_filter == filter_bilinear) + sceGuTexFilter(GU_LINEAR, GU_LINEAR); + else + sceGuTexFilter(GU_NEAREST, GU_NEAREST); + + sceGuFinish(); + sceGuSync(0, 0); + + clear_screen(0x0000); +} + +void video_resolution_small() +{ + if(video_direct != 0) + { + set_gba_resolution(screen_scale); + video_direct = 0; + screen_pixels = screen_texture; + screen_flip = 0; + screen_pitch = 240; + sceGuStart(GU_DIRECT, display_list); + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, + (void*)0, PSP_LINE_SIZE); + sceGuFinish(); + } +} + +void clear_screen(u16 color) +{ + u32 i; + u16 *src_ptr = get_screen_pixels(); + + sceGuSync(0, 0); + + for(i = 0; i < (512 * 272); i++, src_ptr++) + { + *src_ptr = color; + } + + // I don't know why this doesn't work. +/* color = (((color & 0x1F) * 255 / 31) << 0) | + ((((color >> 5) & 0x3F) * 255 / 63) << 8) | + ((((color >> 11) & 0x1F) * 255 / 31) << 16) | (0xFF << 24); + + sceGuStart(GU_DIRECT, display_list); + sceGuDrawBuffer(GU_PSM_5650, (void*)0, PSP_LINE_SIZE); + //sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, + // (void*)0, PSP_LINE_SIZE); + sceGuClearColor(color); + sceGuClear(GU_COLOR_BUFFER_BIT); + sceGuFinish(); + sceGuSync(0, 0); */ +} + +void _flush_cache() +{ + sceKernelDcacheWritebackAll(); +} |