From df894a3a5000bf0f1460767f64c3b78a79f3a457 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 00:16:20 +0200 Subject: [PATCH 01/16] drc: fix BxxZAL Leaving BxxZALL unhadled, need a test as it's real easy to mess it all up here. --- libpcsxcore/new_dynarec/new_dynarec.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 700fab4a..8d3688b1 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -5621,7 +5621,7 @@ void sjump_assemble(int i,struct regstat *i_regs) #endif //if(opcode2[i]>=0x10) return; // FIXME (BxxZAL) - assert(opcode2[i]<0x10||rs1[i]==0); // FIXME (BxxZAL) + //assert(opcode2[i]<0x10||rs1[i]==0); // FIXME (BxxZAL) if(ooo) if(rs1[i]&&(rs1[i]==rt1[i+1]||rs1[i]==rt2[i+1])) @@ -5630,8 +5630,7 @@ void sjump_assemble(int i,struct regstat *i_regs) // First test branch condition, then execute delay slot, then branch ooo=0; } - // TODO: Conditional branches w/link must execute in-order so that - // condition test and write to r31 occur before cycle count test + assert(opcode2[i]<0x10||ooo); // FIXME (BxxZALL) if(ooo) { s1l=get_reg(branch_regs[i].regmap,rs1[i]); @@ -5726,7 +5725,7 @@ void sjump_assemble(int i,struct regstat *i_regs) if(!only32) { assert(s1h>=0); - if(opcode2[i]==0) // BLTZ + if((opcode2[i]&0xf)==0) // BLTZ/BLTZAL { emit_test(s1h,s1h); if(invert){ @@ -5737,7 +5736,7 @@ void sjump_assemble(int i,struct regstat *i_regs) emit_js(0); } } - if(opcode2[i]==1) // BGEZ + if((opcode2[i]&0xf)==1) // BGEZ/BLTZAL { emit_test(s1h,s1h); if(invert){ @@ -5752,7 +5751,7 @@ void sjump_assemble(int i,struct regstat *i_regs) else { assert(s1l>=0); - if(opcode2[i]==0) // BLTZ + if((opcode2[i]&0xf)==0) // BLTZ/BLTZAL { emit_test(s1l,s1l); if(invert){ @@ -5763,7 +5762,7 @@ void sjump_assemble(int i,struct regstat *i_regs) emit_js(0); } } - if(opcode2[i]==1) // BGEZ + if((opcode2[i]&0xf)==1) // BGEZ/BLTZAL { emit_test(s1l,s1l); if(invert){ -- 2.39.2 From 16f7d5e779ba9a142a89f81d520b83dea66ca378 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 01:48:55 +0200 Subject: [PATCH 02/16] fix another alignment issue also switch to PreviousPSXDisplay, it seems to be range checked. --- plugins/dfxvideo/draw_fb.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/dfxvideo/draw_fb.c b/plugins/dfxvideo/draw_fb.c index 5884f928..3e241d7a 100644 --- a/plugins/dfxvideo/draw_fb.c +++ b/plugins/dfxvideo/draw_fb.c @@ -46,25 +46,25 @@ static void blit(void) { extern void bgr555_to_rgb565(void *dst, void *src, int bytes); extern void bgr888_to_rgb888(void *dst, void *src, int bytes); - int x = PSXDisplay.DisplayPosition.x & ~3; // XXX: align needed by bgr*_to_... - int y = PSXDisplay.DisplayPosition.y; + int px = PSXDisplay.DisplayPosition.x & ~3; // XXX: align needed by bgr*_to_... + int py = PSXDisplay.DisplayPosition.y; int w = PreviousPSXDisplay.Range.x1; int h = PreviousPSXDisplay.DisplayMode.y; int pitch = PreviousPSXDisplay.DisplayMode.x; - unsigned short *srcs = psxVuw + y * 1024 + x; + unsigned short *srcs = psxVuw + py * 1024 + px; unsigned char *dest = pl_fbdev_buf; if (w <= 0) return; - // TODO: clear border if centering + // TODO: clear border if centering? pitch *= PSXDisplay.RGB24 ? 3 : 2; // account for centering h -= PreviousPSXDisplay.Range.y0; dest += PreviousPSXDisplay.Range.y0 / 2 * pitch; - dest += PreviousPSXDisplay.Range.x0 * 2; // XXX + dest += (PreviousPSXDisplay.Range.x0 & ~3) * 2; // must align here too.. if (PSXDisplay.RGB24) { @@ -86,15 +86,15 @@ void DoBufferSwap(void) { static int fbw, fbh, fb24bpp; - if (PSXDisplay.DisplayMode.x == 0 || PSXDisplay.DisplayMode.y == 0) + if (PreviousPSXDisplay.DisplayMode.x == 0 || PreviousPSXDisplay.DisplayMode.y == 0) return; /* careful if rearranging this code, we try to set mode and flip * to get the hardware apply both changes at the same time */ - if (PSXDisplay.DisplayMode.x != fbw || PSXDisplay.DisplayMode.y != fbh + if (PreviousPSXDisplay.DisplayMode.x != fbw || PreviousPSXDisplay.DisplayMode.y != fbh || PSXDisplay.RGB24 != fb24bpp) { - fbw = PSXDisplay.DisplayMode.x; - fbh = PSXDisplay.DisplayMode.y; + fbw = PreviousPSXDisplay.DisplayMode.x; + fbh = PreviousPSXDisplay.DisplayMode.y; fb24bpp = PSXDisplay.RGB24; pl_fbdev_set_mode(fbw, fbh, fb24bpp ? 24 : 16); } -- 2.39.2 From 1fd1aceb4382827b39bda6fe6915e38a294534e6 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 14:58:25 +0200 Subject: [PATCH 03/16] drc: fix wrong address reg use in c2ls, small refactoring --- libpcsxcore/new_dynarec/new_dynarec.c | 53 +++++++++++++++------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 8d3688b1..88c059ab 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -3598,7 +3598,7 @@ void c2ls_assemble(int i,struct regstat *i_regs) int s,tl; int ar; int offset; - int c=0; + int memtarget=0,c=0; int jaddr,jaddr2=0,jaddr3,type; int agr=AGEN1+(i&1); u_int hr,reglist=0; @@ -3624,36 +3624,41 @@ void c2ls_assemble(int i,struct regstat *i_regs) } else { // LWC2 ar=tl; } + if(s>=0) c=(i_regs->wasconst>>s)&1; + memtarget=c&&(((signed int)(constmap[i][s]+offset))<(signed int)0x80000000+RAM_SIZE); if (!offset&&!c&&s>=0) ar=s; assert(ar>=0); if (opcode[i]==0x3a) { // SWC2 cop2_get_dreg(copr,tl,HOST_TEMPREG); + type=STOREW_STUB; } - if(s>=0) c=(i_regs->wasconst>>s)&1; - if(!c) { - emit_cmpimm(offset||c||s<0?ar:s,RAM_SIZE); - jaddr2=(int)out; - emit_jno(0); - } - else if(((signed int)(constmap[i][s]+offset))>=(signed int)0x80000000+RAM_SIZE) { - jaddr2=(int)out; - emit_jmp(0); // inline_readstub/inline_writestub? Very rare case - } - if (opcode[i]==0x32) { // LWC2 - #ifdef HOST_IMM_ADDR32 - if(c) emit_readword_tlb(constmap[i][s]+offset,-1,tl); - else - #endif - emit_readword_indexed(0,ar,tl); + else type=LOADW_STUB; + + if(c&&!memtarget) { + jaddr2=(int)out; + emit_jmp(0); // inline_readstub/inline_writestub? } - if (opcode[i]==0x3a) { // SWC2 -#ifdef DESTRUCTIVE_SHIFT - if(!offset&&!c&&s>=0) emit_mov(s,ar); -#endif - emit_writeword_indexed(tl,0,ar); - type=STOREW_STUB; + else { + if(!c) { + emit_cmpimm(offset||c||s<0?ar:s,RAM_SIZE); + jaddr2=(int)out; + emit_jno(0); + } + if (opcode[i]==0x32) { // LWC2 + #ifdef HOST_IMM_ADDR32 + if(c) emit_readword_tlb(constmap[i][s]+offset,-1,tl); + else + #endif + emit_readword_indexed(0,ar,tl); + } + if (opcode[i]==0x3a) { // SWC2 + #ifdef DESTRUCTIVE_SHIFT + if(!offset&&!c&&s>=0) emit_mov(s,ar); + #endif + emit_writeword_indexed(tl,0,ar); + } } if(jaddr2) add_stub(type,jaddr2,(int)out,i,ar,(int)i_regs,ccadj[i],reglist); @@ -3964,7 +3969,7 @@ void address_generation(int i,struct regstat *i_regs,signed char entry[]) if(itype[i]==C1LS||itype[i]==C2LS) { if ((opcode[i]&0x3b)==0x31||(opcode[i]&0x3b)==0x32) // LWC1/LDC1/LWC2/LDC2 ra=get_reg(i_regs->regmap,FTEMP); - else { // SWC1/SDC1 + else { // SWC1/SDC1/SWC2/SDC2 ra=get_reg(i_regs->regmap,agr); if(ra<0) ra=get_reg(i_regs->regmap,-1); } -- 2.39.2 From 190d491511bed7cc64dbbd755bbf438e90025f39 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 17:43:34 +0200 Subject: [PATCH 04/16] bios: fix firstfile() return value it should only return dir when finds a match, bufile macro already does that. --- libpcsxcore/psxbios.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 005e1bb8..aa49b237 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1869,12 +1869,8 @@ void psxBios_firstfile() { // 42 nfile = 1; if (!strncmp(Ra0, "bu00", 4)) { bufile(1); - v0 = _dir; - } - - if (!strncmp(Ra0, "bu10", 4)) { + } else if (!strncmp(Ra0, "bu10", 4)) { bufile(2); - v0 = _dir; } pc0 = ra; -- 2.39.2 From 6b8a7b882dffec0419c8d4ba9e4caab19b6f1ab8 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 18:01:49 +0200 Subject: [PATCH 05/16] more complete credit listing in readme --- pandora/readme.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pandora/readme.txt b/pandora/readme.txt index 36c55d95..5b094504 100644 --- a/pandora/readme.txt +++ b/pandora/readme.txt @@ -35,10 +35,38 @@ Credits / License ----------------- (C) 1999-2003 PCSX Team + (c) 1998 Vision Thing + Linuzappz + Shadow + Pete Bernett + NoComp + Nik3d + Akumax + (C) 2005-2009 PCSX-df Team + (c) Ryan Schultz + (c) Andrew Burton + (c) Stephen Chao + (c) Marcus Comstedt + Stefan Sikora + (C) 2009-2010 PCSX-Reloaded Team + avlex (Help on xcode project) + Dario (Various bugfixes) + edgbla (Root counters, various core/plugin fixes) + Firnis (GTE code from PCSX-Revolution Project) + Gabriele Gorla (MDEC decoder) + maggix (Snow Leopard compile fix) + NeToU (Bugfix) + Peter Collingbourne (Various core/psxbios fixes) + siveritas (Bugfix) + shalma (GTE Divider, various core fixes) + Tristin Celestin (PulseAudio support) + Wei Mingzhi (Maintainer, input plugin, iso/cheat support, misc stuff) + GPU and SPU code by Pete Bernert and the P.E.Op.S. team ARM recompiler (C) 2009-2010 Ari64 + integration, optimization and frontend (C) 2010 notaz Source code is released under GNU GPL license, version 2 or later. -- 2.39.2 From 6d1a1ac2f1100c69dd3e1084aede6646d6c48f1e Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 18:33:34 +0200 Subject: [PATCH 06/16] move layer control to plugin/plugin_lib --- frontend/menu.c | 15 ++++++++++++--- frontend/plugin_lib.c | 16 +++++++++------- frontend/plugin_lib.h | 4 ++-- plugins/dfxvideo/draw_fb.c | 4 ++-- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/frontend/menu.c b/frontend/menu.c index 04a22faf..e46b50f9 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -1032,13 +1032,16 @@ void menu_notify_mode_change(int w, int h, int bpp) if (scaling == SCALE_1_1) { g_layer_x = 800/2 - w/2; g_layer_y = 480/2 - h/2; g_layer_w = w; g_layer_h = h; - omap_enable_layer(1); } } static void menu_leave_emu(void) { - omap_enable_layer(0); + if (GPU_close != NULL) { + int ret = GPU_close(); + if (ret) + fprintf(stderr, "Warning: GPU_close returned %d\n", ret); + } memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2); if (ready_to_go && last_psx_bpp == 16) { @@ -1077,7 +1080,6 @@ void menu_prepare_emu(void) case SCALE_CUSTOM: break; } - omap_enable_layer(1); apply_filter(filter); apply_cpu_clock(); stop = 0; @@ -1086,6 +1088,13 @@ void menu_prepare_emu(void) // so handle them manually here if (Config.Cdda) CDR_stop(); + + if (GPU_open != NULL) { + extern unsigned long gpuDisp; + int ret = GPU_open(&gpuDisp, "PCSX", NULL); + if (ret) + fprintf(stderr, "Warning: GPU_open returned %d\n", ret); + } } void me_update_msg(const char *msg) diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 800a1ae4..0ca45ce6 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -62,12 +62,6 @@ static void print_cpu_usage(void) pl_text_out16(pl_fbdev_w - 28, pl_fbdev_h - 10, "%3d", tick_per_sec); } -int pl_fbdev_init(void) -{ - pl_fbdev_buf = vout_fbdev_flip(layer_fb); - return 0; -} - int pl_fbdev_set_mode(int w, int h, int bpp) { void *ret; @@ -103,8 +97,16 @@ void pl_fbdev_flip(void) pl_fbdev_buf = vout_fbdev_flip(layer_fb); } -void pl_fbdev_finish(void) +int pl_fbdev_open(void) +{ + pl_fbdev_buf = vout_fbdev_flip(layer_fb); + omap_enable_layer(1); + return 0; +} + +void pl_fbdev_close(void) { + omap_enable_layer(0); } static void update_input(void) diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h index a1400e93..81999a33 100644 --- a/frontend/plugin_lib.h +++ b/frontend/plugin_lib.h @@ -21,10 +21,10 @@ enum { extern void *pl_fbdev_buf; -int pl_fbdev_init(void); +int pl_fbdev_open(void); int pl_fbdev_set_mode(int w, int h, int bpp); void pl_fbdev_flip(void); -void pl_fbdev_finish(void); +void pl_fbdev_close(void); void pl_text_out16(int x, int y, const char *texto, ...); diff --git a/plugins/dfxvideo/draw_fb.c b/plugins/dfxvideo/draw_fb.c index 3e241d7a..64657bb2 100644 --- a/plugins/dfxvideo/draw_fb.c +++ b/plugins/dfxvideo/draw_fb.c @@ -137,7 +137,7 @@ unsigned long ulInitDisplay(void) iShowFPS=1; initialize(); - if (pl_fbdev_init() != 0) + if (pl_fbdev_open() != 0) return 0; return 1; /* ok */ @@ -146,7 +146,7 @@ unsigned long ulInitDisplay(void) void CloseDisplay(void) { CloseMenu(); - pl_fbdev_finish(); + pl_fbdev_close(); //WriteConfig(); } -- 2.39.2 From cd6e8d0f6f7596fc25c30b352d4785e74af3edf6 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 28 Dec 2010 19:15:11 +0200 Subject: [PATCH 07/16] add per game configs (by popular demand, no controls yet though) --- frontend/main.c | 1 + frontend/menu.c | 58 ++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/frontend/main.c b/frontend/main.c index 23ed7b14..15e2be40 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -54,6 +54,7 @@ static void CheckSubDir() { create_profile_dir(PLUGINS_CFG_DIR); create_profile_dir(CHEATS_DIR); create_profile_dir(PATCHES_DIR); + create_profile_dir(PCSX_DOT_DIR "cfg"); } void set_cd_image(const char *fname) diff --git a/frontend/menu.c b/frontend/menu.c index e46b50f9..bb2a8935 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -177,6 +177,10 @@ static const struct { CE_CONFIG_VAL(Cpu), CE_CONFIG_VAL(PsxType), CE_INTVAL(scaling), + CE_INTVAL(g_layer_x), + CE_INTVAL(g_layer_y), + CE_INTVAL(g_layer_w), + CE_INTVAL(g_layer_h), CE_INTVAL(filter), CE_INTVAL(state_slot), CE_INTVAL(cpu_clock), @@ -191,16 +195,30 @@ static const struct { CE_INTVAL(iUseTimer), }; +static void make_cfg_fname(char *buf, size_t size, int is_game) +{ + char trimlabel[33]; + int j; + + strncpy(trimlabel, CdromLabel, 32); + trimlabel[32] = 0; + for (j = 31; j >= 0; j--) + if (trimlabel[j] == ' ') + trimlabel[j] = 0; + + if (is_game) + snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", trimlabel, CdromId); + else + snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "%s", cfgfile_basename); +} + static int menu_write_config(int is_game) { char cfgfile[MAXPATHLEN]; FILE *f; int i; - if (is_game) - return -1; - - snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "%s", cfgfile_basename); + make_cfg_fname(cfgfile, sizeof(cfgfile), is_game); f = fopen(cfgfile, "w"); if (f == NULL) { printf("failed to open: %s\n", cfgfile); @@ -256,10 +274,7 @@ static int menu_load_config(int is_game) char *cfg; FILE *f; - if (is_game) - return -1; - - snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "%s", cfgfile_basename); + make_cfg_fname(cfgfile, sizeof(cfgfile), is_game); f = fopen(cfgfile, "r"); if (f == NULL) { printf("failed to open: %s\n", cfgfile); @@ -548,19 +563,12 @@ static const char *mgn_saveloadcfg(int id, int *offs) return ""; } -static int mh_saveloadcfg(int id, int keys) +static int mh_savecfg(int id, int keys) { - switch (id) { - case MA_OPT_SAVECFG: - case MA_OPT_SAVECFG_GAME: - if (menu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0) == 0) - me_update_msg("config saved"); - else - me_update_msg("failed to write config"); - break; - default: - return 0; - } + if (menu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0) == 0) + me_update_msg("config saved"); + else + me_update_msg("failed to write config"); return 1; } @@ -570,8 +578,8 @@ static menu_entry e_menu_keyconfig[] = mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap), mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap), mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap), - mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), -// mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg), +// mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg), +// mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg), mee_label (""), mee_label ("Input devices:"), mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name), @@ -801,8 +809,8 @@ static menu_entry e_menu_options[] = mee_handler ("[Display]", menu_loop_gfx_options), mee_handler ("[BIOS/Plugins]", menu_loop_plugin_options), mee_handler ("[Advanced]", menu_loop_adv_options), - mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), -// mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg), + mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg), + mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg), mee_handler_h ("Restore default config", mh_restore_defaults, h_restore_def), mee_end, }; @@ -814,7 +822,7 @@ static int menu_loop_options(int id, int keys) i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS); e_menu_options[i].enabled = cpu_clock != 0 ? 1 : 0; -// me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go); + me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, ready_to_go); me_loop(e_menu_options, &sel, NULL); -- 2.39.2 From bbd837c6d8a14e76c19028c84ef62a3b8cf0c1f0 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 29 Dec 2010 00:15:55 +0200 Subject: [PATCH 08/16] add some plugin control from the menu, include spunull some random refactoring too. --- Makefile | 7 +- frontend/main.c | 12 ++- frontend/menu.c | 172 ++++++++++++++++++++++++++++++++++--------- frontend/plat_omap.c | 2 +- 4 files changed, 149 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index f195b9b6..724fdbc8 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ $(TARGET): $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) -Wl,-Map=$@.map spunull.so: plugins/spunull/spunull.c - $(CC) $(CFLAGS) -shared -fPIC -o $@ $^ + $(CC) $(CFLAGS) -shared -fPIC -ggdb -O2 -o $@ $^ clean: $(RM) $(TARGET) $(OBJS) @@ -97,9 +97,10 @@ PND_MAKE ?= $(HOME)/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh VER ?= $(shell git describe --abbrev=0 master) -rel: pcsx pandora/pcsx.sh pandora/pcsx.pxml pandora/pcsx.png \ +rel: pcsx spunull.so pandora/pcsx.sh pandora/pcsx.pxml pandora/pcsx.png \ pandora/picorestore pandora/readme.txt skin COPYING rm -rf out - mkdir out + mkdir -p out/plugins cp -r $^ out/ + mv out/*.so out/plugins/ $(PND_MAKE) -p pcsx_rearmed_$(VER).pnd -d out -x pandora/pcsx.pxml -i pandora/pcsx.png -c diff --git a/frontend/main.c b/frontend/main.c index 15e2be40..643d6fe1 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -163,7 +163,6 @@ int main(int argc, char *argv[]) strcpy(Config.Net, "Disabled"); CheckSubDir(); -// ScanAllPlugins(); MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd"); MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd"); @@ -209,8 +208,8 @@ int main(int argc, char *argv[]) return 1; } - SysReset(); CheckCdrom(); + SysReset(); if (file[0] != '\0') { if (Load(file) != -1) @@ -423,9 +422,11 @@ static const int builtin_plugin_ids[] = { void *SysLoadLibrary(const char *lib) { const char *tmp = strrchr(lib, '/'); + void *ret; int i; - printf("dlopen %s\n", lib); + printf("plugin: %s\n", lib); + if (tmp != NULL) { tmp++; for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++) @@ -440,7 +441,10 @@ void *SysLoadLibrary(const char *lib) { lib = name; #endif - return dlopen(lib, RTLD_NOW); + ret = dlopen(lib, RTLD_NOW); + if (ret == NULL) + fprintf(stderr, "dlopen: %s\n", dlerror()); + return ret; } void *SysLoadSym(void *lib, const char *sym) { diff --git a/frontend/menu.c b/frontend/menu.c index bb2a8935..592eb78a 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "menu.h" #include "config.h" @@ -56,7 +57,6 @@ enum { }; extern int ready_to_go; -static int game_config_loaded; static int last_psx_w, last_psx_h, last_psx_bpp; static int scaling, filter, state_slot, cpu_clock; static char rom_fname_reload[MAXPATHLEN]; @@ -75,6 +75,10 @@ extern int iXAPitch; extern int iSPUIRQWait; extern int iUseTimer; +static const char *gpu_plugins[16]; +static const char *spu_plugins[16]; +static int gpu_plugsel, spu_plugsel; + static int min(int x, int y) { return x < y ? x : y; } static int max(int x, int y) { return x > y ? x : y; } @@ -207,9 +211,9 @@ static void make_cfg_fname(char *buf, size_t size, int is_game) trimlabel[j] = 0; if (is_game) - snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", trimlabel, CdromId); + snprintf(buf, size, "." PCSX_DOT_DIR "cfg/%.32s-%.9s.cfg", trimlabel, CdromId); else - snprintf(cfgfile, sizeof(cfgfile), "." PCSX_DOT_DIR "%s", cfgfile_basename); + snprintf(buf, size, "." PCSX_DOT_DIR "%s", cfgfile_basename); } static int menu_write_config(int is_game) @@ -221,7 +225,7 @@ static int menu_write_config(int is_game) make_cfg_fname(cfgfile, sizeof(cfgfile), is_game); f = fopen(cfgfile, "w"); if (f == NULL) { - printf("failed to open: %s\n", cfgfile); + printf("menu_write_config: failed to open: %s\n", cfgfile); return -1; } @@ -277,7 +281,7 @@ static int menu_load_config(int is_game) make_cfg_fname(cfgfile, sizeof(cfgfile), is_game); f = fopen(cfgfile, "r"); if (f == NULL) { - printf("failed to open: %s\n", cfgfile); + printf("menu_load_config: failed to open: %s\n", cfgfile); return -1; } @@ -346,6 +350,16 @@ static int menu_load_config(int is_game) } } + // sync plugins + for (i = gpu_plugsel = 0; gpu_plugins[i] != NULL; i++) + if (strcmp(Config.Gpu, gpu_plugins[i]) == 0) + { gpu_plugsel = i; break; } + + for (i = spu_plugsel = 0; spu_plugins[i] != NULL; i++) + if (strcmp(Config.Spu, spu_plugins[i]) == 0) + { spu_plugsel = i; break; } + + ret = 0; fail_read: free(cfg); fail: @@ -679,8 +693,6 @@ static int menu_loop_gfx_options(int id, int keys) // ------------ bios/plugins ------------ static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL }; -static const char h_gpu[] = "Configure built-in P.E.Op.S. SoftGL Driver V1.17\n" - "Coded by Pete Bernert and the P.E.Op.S. team"; static const char h_gpu_0[] = "Needed for Chrono Cross"; static const char h_gpu_1[] = "Capcom fighting games"; static const char h_gpu_2[] = "Black screens in Lunar"; @@ -715,8 +727,6 @@ static int menu_loop_plugin_gpu(int id, int keys) static const char *men_spu_reverb[] = { "Off", "Fake", "On", NULL }; static const char *men_spu_interp[] = { "None", "Simple", "Gaussian", "Cubic", NULL }; -static const char h_spu[] = "Configure built-in P.E.Op.S. Sound Driver V1.7\n" - "Coded by Pete Bernert and the P.E.Op.S. team"; static const char h_spu_irq_wait[] = "Wait for CPU; only useful for some games, may cause glitches"; static const char h_spu_thread[] = "Run sound emulation in separate thread"; @@ -737,8 +747,15 @@ static int menu_loop_plugin_spu(int id, int keys) return 0; } +static const char h_gpu[] = "Configure built-in P.E.Op.S. SoftGL Driver V1.17"; +static const char h_spu[] = "Configure built-in P.E.Op.S. Sound Driver V1.7"; +static const char h_plugin_xpu[] = "Must save config and reload the game\n" + "for plugin change to take effect"; + static menu_entry e_menu_plugin_options[] = { + mee_enum_h ("GPU plugin", 0, gpu_plugsel, gpu_plugins, h_plugin_xpu), + mee_enum_h ("SPU plugin", 0, spu_plugsel, spu_plugins, h_plugin_xpu), mee_handler_h ("Configure built-in GPU plugin", menu_loop_plugin_gpu, h_gpu), mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu), mee_end, @@ -748,6 +765,11 @@ static int menu_loop_plugin_options(int id, int keys) { static int sel = 0; me_loop(e_menu_plugin_options, &sel, NULL); + + // sync plugins + snprintf(Config.Gpu, sizeof(Config.Gpu), "%s", gpu_plugins[gpu_plugsel]); + snprintf(Config.Spu, sizeof(Config.Spu), "%s", spu_plugins[spu_plugsel]); + return 0; } @@ -870,52 +892,72 @@ const char *plat_get_credits(void) " frontend (C) 2010 notaz\n"; } -static char *romsel_run(void) +static int run_cd_image(const char *fname) { extern void set_cd_image(const char *fname); - char *ret; - - ret = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname)); - if (ret == NULL) - return NULL; - - lprintf("selected file: %s\n", ret); ready_to_go = 0; - set_cd_image(ret); + set_cd_image(fname); LoadPlugins(); NetOpened = 0; if (OpenPlugins() == -1) { me_update_msg("failed to open plugins"); - return NULL; + return -1; } - SysReset(); - if (CheckCdrom() == -1) { // Only check the CD if we are starting the console with a CD ClosePlugins(); me_update_msg("unsupported/invalid CD image"); - return NULL; + return -1; } + SysReset(); + // Read main executable directly from CDRom and start it if (LoadCdrom() == -1) { ClosePlugins(); me_update_msg("failed to load CD image"); - return NULL; + return -1; } - strcpy(last_selected_fname, rom_fname_reload); - game_config_loaded = 0; ready_to_go = 1; - return ret; + return 0; } -static int main_menu_handler(int id, int keys) +static int romsel_run(void) { - char *ret_name; + int prev_gpu, prev_spu; + char *fname; + + fname = menu_loop_romsel(last_selected_fname, sizeof(last_selected_fname)); + if (fname == NULL) + return -1; + printf("selected file: %s\n", fname); + + if (run_cd_image(fname) != 0) + return -1; + + prev_gpu = gpu_plugsel; + prev_spu = spu_plugsel; + if (menu_load_config(1) != 0) + menu_load_config(0); + + // check for plugin changes, have to repeat + // loading if game config changed plugins to reload them + if (prev_gpu != gpu_plugsel || prev_spu != spu_plugsel) { + printf("plugin change detected, reloading plugins..\n"); + if (run_cd_image(fname) != 0) + return -1; + } + + strcpy(last_selected_fname, rom_fname_reload); + return 0; +} + +static int main_menu_handler(int id, int keys) +{ switch (id) { case MA_MAIN_RESUME_GAME: @@ -941,8 +983,7 @@ static int main_menu_handler(int id, int keys) } break; case MA_MAIN_LOAD_ROM: - ret_name = romsel_run(); - if (ret_name != NULL) + if (romsel_run() == 0) return 1; break; case MA_MAIN_CREDITS: @@ -1009,12 +1050,77 @@ void menu_loop(void) menu_prepare_emu(); } +static void scan_plugins(void) +{ + char fname[MAXPATHLEN]; + struct dirent *ent; + int gpu_i, spu_i; + char *p; + DIR *dir; + + gpu_plugins[0] = "builtin_gpu"; + spu_plugins[0] = "builtin_spu"; + gpu_i = spu_i = 1; + + snprintf(fname, sizeof(fname), "%s/", Config.PluginsDir); + dir = opendir(fname); + if (dir == NULL) { + perror("scan_plugins opendir"); + return; + } + + while (1) { + void *h, *tmp; + + errno = 0; + ent = readdir(dir); + if (ent == NULL) { + if (errno != 0) + perror("readdir"); + break; + } + p = strstr(ent->d_name, ".so"); + if (p == NULL) + continue; + + snprintf(fname, sizeof(fname), "%s/%s", Config.PluginsDir, ent->d_name); + h = dlopen(fname, RTLD_LAZY | RTLD_LOCAL); + if (h == NULL) { + fprintf(stderr, "%s\n", dlerror()); + continue; + } + + // now what do we have here? + tmp = dlsym(h, "GPUinit"); + if (tmp) { + dlclose(h); + if (gpu_i < ARRAY_SIZE(gpu_plugins) - 1) + gpu_plugins[gpu_i++] = strdup(ent->d_name); + continue; + } + + tmp = dlsym(h, "SPUinit"); + if (tmp) { + dlclose(h); + if (spu_i < ARRAY_SIZE(spu_plugins) - 1) + spu_plugins[spu_i++] = strdup(ent->d_name); + continue; + } + + fprintf(stderr, "ignoring unidentified plugin: %s\n", fname); + dlclose(h); + } + + closedir(dir); +} + void menu_init(void) { char buff[MAXPATHLEN]; strcpy(last_selected_fname, "/media"); + scan_plugins(); pnd_menu_init(); menu_init_common(); @@ -1067,12 +1173,6 @@ static void menu_leave_emu(void) void menu_prepare_emu(void) { - if (!game_config_loaded) { - menu_set_defconfig(); - menu_load_config(1); - game_config_loaded = 1; - } - switch (scaling) { case SCALE_1_1: menu_notify_mode_change(last_psx_w, last_psx_h, last_psx_bpp); diff --git a/frontend/plat_omap.c b/frontend/plat_omap.c index 710a45be..ec483a04 100644 --- a/frontend/plat_omap.c +++ b/frontend/plat_omap.c @@ -151,7 +151,7 @@ void plat_init(void) exit(1); } - ret = omap_setup_layer_(fd, 1, g_layer_x, g_layer_y, g_layer_w, g_layer_h, 1); + ret = omap_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h, 1); close(fd); if (ret != 0) { fprintf(stderr, "failed to set up layer, exiting.\n"); -- 2.39.2 From 9af2e936a15a487f3920a198213387ef2c1a02ac Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 29 Dec 2010 01:01:11 +0200 Subject: [PATCH 09/16] release r2 --- pandora/readme.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pandora/readme.txt b/pandora/readme.txt index 5b094504..51ca33df 100644 --- a/pandora/readme.txt +++ b/pandora/readme.txt @@ -31,6 +31,27 @@ Supportd CD image formats: CDDA (CD audio) support requires .cue/.bin format. +Changelog +--------- + +r2: +* fixed memcard paths +* fixed a keybind copy-paste bug +* properly implemented pad handling + (inputs no longer controls both emulated pads at once) +* fixed a crash caused by framebuffer out of range access +* fixed SWL/SWR handling (usually resulted in graphic glitches) +* fixed BxxZAL (Medal of Honor) +* fixed alignment crash in color space conversion code (Lunar) +* fixed SWC2 occasional use of wrong address register (Parasite Eve) +* fixed firstfile() handling in HLE BIOS (broken memory cards in some games) ++ added per-game configs (controls still not saved though) ++ added simple plugin select interface to the menu + +r1: +* initial release + + Credits / License ----------------- -- 2.39.2 From dc40e780e5645e55afb914c752734678361ad733 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 30 Dec 2010 17:40:23 +0200 Subject: [PATCH 10/16] decouple input/frame limiter from GPU plugin --- libpcsxcore/psxcommon.c | 1 + plugins/dfxvideo/gpu.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libpcsxcore/psxcommon.c b/libpcsxcore/psxcommon.c index f118c2db..5e9dcafb 100644 --- a/libpcsxcore/psxcommon.c +++ b/libpcsxcore/psxcommon.c @@ -56,6 +56,7 @@ void EmuUpdate() { if (!Config.HLE || !hleSoftCall) SysUpdate(); + pl_frame_limit(); ApplyCheats(); } diff --git a/plugins/dfxvideo/gpu.c b/plugins/dfxvideo/gpu.c index 87eeca30..2b12fd79 100644 --- a/plugins/dfxvideo/gpu.c +++ b/plugins/dfxvideo/gpu.c @@ -789,9 +789,9 @@ void CALLBACK GPUupdateLace(void) // VSYNC if(!(dwActFixes&1)) lGPUstatusRet^=0x80000000; // odd/even bit + //pcsx-rearmed: removed, this is handled by core //if(!(dwActFixes&32)) // std fps limitation? // CheckFrameRate(); - pl_frame_limit(); if(PSXDisplay.Interlaced) // interlaced mode? { -- 2.39.2 From e0ff987cf1f0e8ee87da5b97bd6574f543b69c4c Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Dec 2010 01:24:21 +0200 Subject: [PATCH 11/16] fbdev: resize: do single ioctl in nonerror path --- frontend/linux/fbdev.c | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/frontend/linux/fbdev.c b/frontend/linux/fbdev.c index 224f42d8..da73b1ab 100644 --- a/frontend/linux/fbdev.c +++ b/frontend/linux/fbdev.c @@ -74,43 +74,45 @@ void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp, ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK); if (fbdev->fbvar_new.bits_per_pixel != bpp || - w != fbdev->fbvar_new.xres || - h != fbdev->fbvar_new.yres || - w_total != fbdev->fbvar_new.xres_virtual || - h_total > fbdev->fbvar_new.yres_virtual || - left_border != fbdev->fbvar_new.xoffset) { + fbdev->fbvar_new.xres != w || + fbdev->fbvar_new.yres != h || + fbdev->fbvar_new.xres_virtual != w_total|| + fbdev->fbvar_new.yres_virtual < h_total || + fbdev->fbvar_new.xoffset != left_border || + fbdev->buffer_count != buffer_cnt) + { + if (fbdev->fbvar_new.bits_per_pixel != bpp || + w != fbdev->fbvar_new.xres || h != fbdev->fbvar_new.yres) + printf(" switching to %dx%d@%d\n", w, h, bpp); + fbdev->fbvar_new.xres = w; fbdev->fbvar_new.yres = h; fbdev->fbvar_new.xres_virtual = w_total; - fbdev->fbvar_new.yres_virtual = h_total; + fbdev->fbvar_new.yres_virtual = h_total * buffer_cnt; fbdev->fbvar_new.xoffset = left_border; fbdev->fbvar_new.yoffset = top_border; fbdev->fbvar_new.bits_per_pixel = bpp; - printf(" switching to %dx%d@%d\n", w, h, bpp); + fbdev->buffer_count = buffer_cnt; + fbdev->buffer_write = 1; // seems to help a bit to avoid glitches vout_fbdev_wait_vsync(fbdev); ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); if (ret == -1) { - perror("FBIOPUT_VSCREENINFO ioctl"); - return NULL; - } - - fbdev->buffer_write = 1; - } - - fbdev->buffer_count = buffer_cnt; - - if (fbdev->fbvar_new.yres_virtual < h_total * fbdev->buffer_count) { - fbdev->fbvar_new.yres_virtual = h_total * fbdev->buffer_count; - ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); - if (ret == -1) { + // retry with no multibuffering + fbdev->fbvar_new.yres_virtual = h_total; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); + if (ret == -1) { + perror("FBIOPUT_VSCREENINFO ioctl"); + return NULL; + } fbdev->buffer_count = 1; fbdev->buffer_write = 0; fprintf(stderr, "Warning: failed to increase virtual resolution, " - "doublebuffering disabled\n"); + "multibuffering disabled\n"); } + } fbdev->fb_size = w_total * h_total * bpp / 8; -- 2.39.2 From fba064572196c69de43e3c69245369d94d3be929 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Dec 2010 01:43:28 +0200 Subject: [PATCH 12/16] prepare for external gpu plugins also fixes framelimiter and some config being overwritten by dfxvideo --- frontend/common/plat.h | 1 + frontend/menu.c | 27 +++++++++++++++++++++++---- frontend/plat_omap.c | 19 +++++++++++++++++++ plugins/dfxvideo/cfg.c | 9 +++++---- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/frontend/common/plat.h b/frontend/common/plat.h index c16f8885..03570406 100644 --- a/frontend/common/plat.h +++ b/frontend/common/plat.h @@ -33,6 +33,7 @@ void plat_status_msg_clear(void); void plat_video_menu_enter(int is_rom_loaded); void plat_video_menu_begin(void); void plat_video_menu_end(void); +void plat_video_menu_leave(void); void plat_video_flip(void); void plat_video_wait_vsync(void); diff --git a/frontend/menu.c b/frontend/menu.c index 592eb78a..0469868a 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -66,7 +66,10 @@ int g_opts; // from softgpu plugin extern int iUseDither; extern int UseFrameSkip; +extern int UseFrameLimit; extern uint32_t dwActFixes; +extern float fFrameRateHz; +extern int dwFrameRateTicks; // sound plugin extern int iUseReverb; @@ -139,6 +142,7 @@ static void menu_set_defconfig(void) Config.SpuIrq = Config.RCntFix = Config.VSyncWA = 0; iUseDither = UseFrameSkip = 0; + UseFrameLimit = 1; dwActFixes = 1<<7; iUseReverb = 2; @@ -191,6 +195,7 @@ static const struct { CE_INTVAL(g_opts), CE_INTVAL(iUseDither), CE_INTVAL(UseFrameSkip), + CE_INTVAL(UseFrameLimit), CE_INTVAL(dwActFixes), CE_INTVAL(iUseReverb), CE_INTVAL(iUseInterpolation), @@ -775,6 +780,8 @@ static int menu_loop_plugin_options(int id, int keys) // ------------ adv options menu ------------ +static const char h_cfg_cpul[] = "Shows CPU usage in %%"; +static const char h_cfg_fl[] = "Keeps the game from running too fast"; static const char h_cfg_xa[] = "Disables XA sound, which can sometimes improve performance"; static const char h_cfg_cdda[] = "Disable CD Audio for a performance boost\n" "(proper .cue/.bin dump is needed otherwise)"; @@ -785,7 +792,8 @@ static const char h_cfg_rcnt2[] = "InuYasha Sengoku Battle Fix"; static menu_entry e_menu_adv_options[] = { - mee_onoff ("Show CPU load", 0, g_opts, OPT_SHOWCPU), + mee_onoff_h ("Show CPU load", 0, g_opts, OPT_SHOWCPU, h_cfg_cpul), + mee_onoff_h ("Frame Limiter", 0, UseFrameLimit, 1, h_cfg_fl), mee_onoff_h ("Disable XA Decoding", 0, Config.Xa, 1, h_cfg_xa), mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda), mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio), @@ -896,7 +904,9 @@ static int run_cd_image(const char *fname) { extern void set_cd_image(const char *fname); ready_to_go = 0; + pl_fbdev_buf = NULL; + ClosePlugins(); set_cd_image(fname); LoadPlugins(); NetOpened = 0; @@ -974,6 +984,7 @@ static int main_menu_handler(int id, int keys) break; case MA_MAIN_RESET_GAME: if (ready_to_go) { + ClosePlugins(); OpenPlugins(); SysReset(); if (CheckCdrom() != -1) { @@ -1045,8 +1056,6 @@ void menu_loop(void) in_set_config_int(0, IN_CFG_BLOCKING, 0); - memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2); - menu_draw_end(); menu_prepare_emu(); } @@ -1158,7 +1167,7 @@ static void menu_leave_emu(void) } memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2); - if (ready_to_go && last_psx_bpp == 16) { + if (pl_fbdev_buf != NULL && ready_to_go && last_psx_bpp == 16) { int x = max(0, g_menuscreen_w - last_psx_w); int y = max(0, g_menuscreen_h / 2 - last_psx_h / 2); int w = min(g_menuscreen_w, last_psx_w); @@ -1169,10 +1178,14 @@ static void menu_leave_emu(void) for (; h > 0; h--, d += g_menuscreen_w, s += last_psx_w) menu_darken_bg(d, s, w, 0); } + + plat_video_menu_enter(ready_to_go); } void menu_prepare_emu(void) { + plat_video_menu_leave(); + switch (scaling) { case SCALE_1_1: menu_notify_mode_change(last_psx_w, last_psx_h, last_psx_bpp); @@ -1197,6 +1210,12 @@ void menu_prepare_emu(void) if (Config.Cdda) CDR_stop(); + // HACK to set up the frame limiter if softgpu is not used.. + if (gpu_plugsel != 0) { + fFrameRateHz = Config.PsxType ? 50.0f : 59.94f; + dwFrameRateTicks = (100000*100 / (unsigned long)(fFrameRateHz*100)); + } + if (GPU_open != NULL) { extern unsigned long gpuDisp; int ret = GPU_open(&gpuDisp, "PCSX", NULL); diff --git a/frontend/plat_omap.c b/frontend/plat_omap.c index ec483a04..e6a1105d 100644 --- a/frontend/plat_omap.c +++ b/frontend/plat_omap.c @@ -120,6 +120,14 @@ int omap_enable_layer(int enabled) g_layer_x, g_layer_y, g_layer_w, g_layer_h, 0); } +void plat_video_menu_enter(int is_rom_loaded) +{ + g_menuscreen_ptr = vout_fbdev_resize(main_fb, + g_menuscreen_w, g_menuscreen_h, 16, 0, 0, 0, 0, 3); + if (g_menuscreen_ptr == NULL) + fprintf(stderr, "warning: vout_fbdev_resize failed\n"); +} + void plat_video_menu_begin(void) { } @@ -129,6 +137,17 @@ void plat_video_menu_end(void) g_menuscreen_ptr = vout_fbdev_flip(main_fb); } +void plat_video_menu_leave(void) +{ + /* have to get rid of panning so that plugins that + * use fb0 and don't ever pan can work. */ + vout_fbdev_clear(main_fb); + g_menuscreen_ptr = vout_fbdev_resize(main_fb, + g_menuscreen_w, g_menuscreen_h, 16, 0, 0, 0, 0, 1); + if (g_menuscreen_ptr == NULL) + fprintf(stderr, "warning: vout_fbdev_resize failed\n"); +} + void plat_init(void) { const char *main_fb_name, *layer_fb_name; diff --git a/plugins/dfxvideo/cfg.c b/plugins/dfxvideo/cfg.c index dbc3bc58..710883b5 100644 --- a/plugins/dfxvideo/cfg.c +++ b/plugins/dfxvideo/cfg.c @@ -221,15 +221,16 @@ void ReadConfigGPU(void) iColDepth=32; iWindowMode=1; iMaintainAspect=0; - UseFrameLimit=1; - UseFrameSkip=0; iFrameLimit=2; fFrameRate=200.0f; - dwCfgFixes=0; iUseFixes=0; iUseNoStretchBlt=0; - iUseDither=0; iShowFPS=0; + // pcsx-rearmed: managed by frontend + //UseFrameLimit=1; + //UseFrameSkip=0; + //dwCfgFixes=0; + //iUseDither=0; // read sets ReadConfigFile(); -- 2.39.2 From 3a255ce52a55a2065429b8baad000c72aed31e97 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Dec 2010 01:56:25 +0200 Subject: [PATCH 13/16] gui/Plugin: don't open/close gpu this is handled by frontend, so prevent double open/close --- gui/Plugin.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/gui/Plugin.c b/gui/Plugin.c index 867fce03..72184167 100644 --- a/gui/Plugin.c +++ b/gui/Plugin.c @@ -289,8 +289,9 @@ int _OpenPlugins() { ret = SPU_open(); if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; } SPU_registerCallback(SPUirq); - ret = GPU_open(&gpuDisp, "PCSX", NULL); - if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; } + // pcsx-rearmed: we handle gpu elsewhere + //ret = GPU_open(&gpuDisp, "PCSX", NULL); + //if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; } ret = PAD1_open(&gpuDisp); if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; } ret = PAD2_open(&gpuDisp); @@ -381,8 +382,9 @@ void ClosePlugins() { if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; } ret = PAD2_close(); if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; } - ret = GPU_close(); - if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; } + // pcsx-rearmed: we handle gpu elsewhere + //ret = GPU_close(); + //if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; } if (Config.UseNet) { NET_pause(); -- 2.39.2 From ce879073e4f228deec8bec5db8a2ff640636c88f Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Dec 2010 16:57:02 +0200 Subject: [PATCH 14/16] gpu-gles from psx4m --- plugins/gpu-gles/gpuDraw.c | 1345 +++++++++ plugins/gpu-gles/gpuDraw.h | 83 + plugins/gpu-gles/gpuExternals.h | 570 ++++ plugins/gpu-gles/gpuFps.c | 991 ++++++ plugins/gpu-gles/gpuFps.h | 66 + plugins/gpu-gles/gpuPlugin.c | 2960 ++++++++++++++++++ plugins/gpu-gles/gpuPlugin.h | 134 + plugins/gpu-gles/gpuPrim.c | 5022 +++++++++++++++++++++++++++++++ plugins/gpu-gles/gpuPrim.h | 58 + plugins/gpu-gles/gpuStdafx.h | 99 + plugins/gpu-gles/gpuTexture.c | 4226 ++++++++++++++++++++++++++ plugins/gpu-gles/gpuTexture.h | 87 + 12 files changed, 15641 insertions(+) create mode 100644 plugins/gpu-gles/gpuDraw.c create mode 100644 plugins/gpu-gles/gpuDraw.h create mode 100644 plugins/gpu-gles/gpuExternals.h create mode 100644 plugins/gpu-gles/gpuFps.c create mode 100644 plugins/gpu-gles/gpuFps.h create mode 100644 plugins/gpu-gles/gpuPlugin.c create mode 100644 plugins/gpu-gles/gpuPlugin.h create mode 100644 plugins/gpu-gles/gpuPrim.c create mode 100644 plugins/gpu-gles/gpuPrim.h create mode 100644 plugins/gpu-gles/gpuStdafx.h create mode 100644 plugins/gpu-gles/gpuTexture.c create mode 100644 plugins/gpu-gles/gpuTexture.h diff --git a/plugins/gpu-gles/gpuDraw.c b/plugins/gpu-gles/gpuDraw.c new file mode 100644 index 00000000..3d09c333 --- /dev/null +++ b/plugins/gpu-gles/gpuDraw.c @@ -0,0 +1,1345 @@ +/*************************************************************************** + draw.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +#define _IN_DRAW + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#include +#include +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#else +#include "gpuExternals.h" +#include "GPUPlugin.h" +#include "gpuDraw.h" +#include "gpuPrim.h" +#include "gpuTexture.h" +#include "gpuStdafx.h" + +#include +#include +#include +#endif +//#include "menu.h" + +//////////////////////////////////////////////////////////////////////////////////// +// defines + +#define SIGNBIT 0x800 +#define S_MASK 0xf000 +#define L_MASK 0xfffff000 + +// ownscale: some ogl drivers have buggy texture matrix funcs, so it +// is safer to calc sow/tow ourselves + +#ifdef OWNSCALE + +/////////////////////////////////////////////////////////////// + +#define ST_FACSPRITE 255.99f +#define ST_BFFACSPRITE 0.5f/256.0f +#define ST_BFFACSPRITESORT 0.333f/256.0f + +#define ST_OFFSET 0.5f/256.0f; + +#define ST_FAC 255.99f +#define ST_BFFAC 0.5f/256.0f +#define ST_BFFACSORT 0.333f/256.0f + +#define ST_FACTRI 255.99f +#define ST_BFFACTRI 0.5f/256.0f +#define ST_BFFACTRISORT 0.333f/256.0f + +#define ST_FACVRAMX 255.0f +#define ST_FACVRAM 256.0f + +/////////////////////////////////////////////////////////////// + +#else + +#define ST_BFFACSPRITE 0.5f +#define ST_BFFACSPRITESORT 0.333f + +#define ST_BFFAC 0.5f +#define ST_BFFACSORT 0.333f + +#define ST_BFFACTRI 0.5f +#define ST_BFFACTRISORT 0.333f + +#define ST_OFFSET 0.5f; + +#endif + +//////////////////////////////////////////////////////////////////////////////////// +// draw globals + +#ifdef _WINDOWS +HDC dcGlobal=NULL; +HWND hWWindow; +#else +void glBlendEquationEXT(GLenum mode); +void glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data); +#endif + +// draw globals; most will be initialized again later (by config or checks) + +BOOL bIsFirstFrame=TRUE; + +// resolution/ratio vars + +int iResX; +int iResY; +BOOL bKeepRatio=FALSE; +RECT rRatioRect; + +// psx mask related vars + +BOOL bCheckMask=FALSE; +int iUseMask=0; +int iSetMask=0; +unsigned short sSetMask=0; +unsigned long lSetMask=0; + +// drawing/coord vars + +OGLVertex vertex[4]; +GLubyte gl_ux[8]; +GLubyte gl_vy[8]; +short sprtY,sprtX,sprtH,sprtW; + +// drawing options + +BOOL bOpaquePass; +BOOL bAdvancedBlend; + +// OGL extension support + + +// gfx card buffer infos + +int iDepthFunc=0; +int iZBufferDepth=0; +GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT; + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Set OGL pixel format +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +BOOL bSetupPixelFormat(HDC hDC) +{ + int pixelformat; + static PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 16, // 16-bit color depth (adjusted later) + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 0, // z-buffer + 0, + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + pfd.cColorBits=iColDepth; // set user color depth + pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask) + + if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) + { + MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK); + return FALSE; + } + + if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE) + { + MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK); + return FALSE; + } + + return TRUE; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// Get extension infos (f.e. pal textures / packed pixels) +//////////////////////////////////////////////////////////////////////// + +void GetExtInfos(void) +{ + BOOL bPacked=FALSE; // default: no packed pixel support + + if(strstr((s8 *)glGetString(GL_EXTENSIONS), // packed pixels available? + "GL_EXT_packed_pixels")) + bPacked=TRUE; // -> ok + + + #ifdef _WINDOWS + iClampType=GL_CLAMP; +#else + iClampType=GL_CLAMP_TO_EDGE; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Setup some stuff depending on user settings or in-game toggle +//////////////////////////////////////////////////////////////////////// + +void SetExtGLFuncs(void) +{ + //----------------------------------------------------// + + SetFixes(); // update fix infos + + //----------------------------------------------------// + + { + if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes + else bUseMultiPass=FALSE; // -> or simple 'bright color' mode +// bGLBlend=FALSE; // -> no ext blending! + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + + if(bOpaquePass) // opaque mode? + { + if(dwActFixes&32) + { + TCF[0]=CP8RGBA_0; + PalTexturedColourFn=CP8RGBA; // -> init col func + } + else + { + TCF[0]=XP8RGBA_0; + PalTexturedColourFn=XP8RGBA; // -> init col func + } + + TCF[1]=XP8RGBA_1; + glAlphaFuncx(GL_GREATER,0.49f); + } + else // no opaque mode? + { + TCF[0]=TCF[1]=P8RGBA; + PalTexturedColourFn=P8RGBA; // -> init col func + glAlphaFuncx(GL_NOTEQUAL,0); // --> set alpha func + } + + //----------------------------------------------------// + + LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr + + bBlendEnable=FALSE; // init blending: off + glDisable(GL_BLEND); + + SetScanTrans(); // init scan lines (if wanted) +} + +//////////////////////////////////////////////////////////////////////// +// setup scan lines +//////////////////////////////////////////////////////////////////////// + +#define R_TSP 0x00,0x45,0x00,0xff +#define G_TSP 0x00,0x00,0x45,0xff +#define B_TSP 0x45,0x00,0x00,0xff +#define O_TSP 0x45,0x45,0x45,0xff +#define N_TSP 0x00,0x00,0x00,0xff + +GLuint gTexScanName=0; + +GLubyte texscan[4][16]= +{ +{R_TSP, G_TSP, B_TSP, N_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP}, +{B_TSP, N_TSP, R_TSP, G_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP} +}; + +void CreateScanLines(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// Initialize OGL +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +HGLRC GLCONTEXT=NULL; +#endif + +#ifdef MAEMO_CHANGES +bool TestEGLError(const char* pszLocation) +{ + /* + eglGetError returns the last error that has happened using egl, + not the status of the last called function. The user has to + check after every single egl call or at least once every frame. + */ + EGLint iErr = eglGetError(); + if (iErr != EGL_SUCCESS) + { + printf("%s failed (%d).\n", pszLocation, iErr); + return false; + } + + return true; +} + +void maemoGLinit(){ + iResX= 800; + iResY =480; + + + printf ("maemo GL init\n"); + long int winxid=GDK_WINDOW_XID(GTK_WIDGET(windowG)->window); + printf ("%d\n",winxid); + + EGLContext context = 0; + EGLConfig eglConfig = 0; + EGLContext eglContext = 0; + display = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + + if( eglInitialize( display, NULL, NULL ) == EGL_FALSE ) + { + printf( "EGL Initialize failed!\n" ); + + } + +const EGLint attributeList[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + /*EGL_BUFFER_SIZE, 32, */ + EGL_NONE + }; + + EGLint pi32ConfigAttribs[5]; + pi32ConfigAttribs[0] = EGL_SURFACE_TYPE; + pi32ConfigAttribs[1] = EGL_WINDOW_BIT; + pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE; + pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT; + pi32ConfigAttribs[4] = EGL_NONE; + + EGLint pi32ContextAttribs[3]; + pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION; + pi32ContextAttribs[1] = 2; + pi32ContextAttribs[2] = EGL_NONE; + + int iConfigs; + if (!eglChooseConfig(display, attributeList, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) + { + printf("Error: eglChooseConfig() failed.\n"); + } + printf ("%d\n",iConfigs); + surface = eglCreateWindowSurface(display, eglConfig, (void*)winxid, NULL); + printf ("%d\n",surface); + if (!TestEGLError("eglCreateWindowSurface")) + { + printf ("eglCreateWindowSurface fail"); + } + + //context = eglCreateContext(display, eglConfig, NULL, pi32ContextAttribs); + context =eglCreateContext( display, eglConfig, + EGL_NO_CONTEXT, NULL + ); +printf ("%d\n",context); + if (!TestEGLError("eglCreateContext")) + { + printf("error eglCreateContext"); + } + + eglMakeCurrent(display, surface, surface, context); + + if (!TestEGLError("eglMakeCurrent")) + { + printf("error eglMakeCurrent"); + } +} +#endif + +int GLinitialize() +{ + //----------------------------------------------------// +#ifdef _WINDOWS + HGLRC objectRC; + // init + dcGlobal = GetDC(hWWindow); // FIRST: dc/rc stuff + objectRC = wglCreateContext(dcGlobal); + GLCONTEXT=objectRC; + wglMakeCurrent(dcGlobal, objectRC); + // CheckWGLExtensions(dcGlobal); + if(bWindowMode) ReleaseDC(hWWindow,dcGlobal); // win mode: release dc again +#endif +#ifdef MAEMO_CHANGES + maemoGLinit(); +#endif + //----------------------------------------------------// + + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + +#ifndef OWNSCALE + glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale" + glLoadIdentity(); + glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack +#endif + + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + + if(iZBufferDepth) // zbuffer? + { + uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT; + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + iDepthFunc=1; + } + else // no zbuffer? + { + uiBufferBits=GL_COLOR_BUFFER_BIT; + glDisable(GL_DEPTH_TEST); + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // first buffer clear + glClear(uiBufferBits); + + GetExtInfos(); // get ext infos + SetExtGLFuncs(); // init all kind of stuff (tex function pointers) + + glEnable(GL_ALPHA_TEST); // wanna alpha test + + { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); + } + + ubGloAlpha=127; // init some drawing vars + ubGloColAlpha=127; + TWin.UScaleFactor = 1; + TWin.VScaleFactor = 1; + bDrawMultiPass=FALSE; + bTexEnabled=FALSE; + bUsingTWin=FALSE; + + if(bDrawDither) glEnable(GL_DITHER); // dither mode + else glDisable(GL_DITHER); + + glDisable(GL_FOG); // turn all (currently) unused modes off + glDisable(GL_LIGHTING); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_CULL_FACE); + + glFlush(); // we are done... + glFinish(); + + CreateScanLines(); // setup scanline stuff (if wanted) + + CheckTextureMemory(); // check available tex memory + + if(bKeepRatio) SetAspectRatio(); // set ratio + + + bIsFirstFrame = FALSE; // we have survived the first frame :) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// clean up OGL stuff +//////////////////////////////////////////////////////////////////////// + +void GLcleanup() +{ + CleanupTextureStore(); // bye textures + +#ifdef _WINDOWS + wglMakeCurrent(NULL, NULL); // bye context + if(GLCONTEXT) wglDeleteContext(GLCONTEXT); + if(!bWindowMode && dcGlobal) + ReleaseDC(hWWindow,dcGlobal); +#endif +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Offset stuff +//////////////////////////////////////////////////////////////////////// + +// please note: it is hardly do-able in a hw/accel plugin to get the +// real psx polygon coord mapping right... the following +// works not to bad with many games, though + +__inline BOOL CheckCoord4() +{ + if(lx0<0) + { + if(((lx1-lx0)>CHKMAX_X) || + ((lx2-lx0)>CHKMAX_X)) + { + if(lx3<0) + { + if((lx1-lx3)>CHKMAX_X) return TRUE; + if((lx2-lx3)>CHKMAX_X) return TRUE; + } + } + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + if((lx3-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + if((lx3-lx2)>CHKMAX_X) return TRUE; + } + if(lx3<0) + { + if(((lx1-lx3)>CHKMAX_X) || + ((lx2-lx3)>CHKMAX_X)) + { + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + } + } + + + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + if((ly3-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + if((ly3-ly2)>CHKMAX_Y) return TRUE; + } + if(ly3<0) + { + if((ly1-ly3)>CHKMAX_Y) return TRUE; + if((ly2-ly3)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoord3() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +__inline BOOL CheckCoord2() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +// Pete's way: a very easy (and hopefully fast) approach for lines +// without sqrt... using a small float -> short cast trick :) + +#define VERTEX_OFFX 0.2f +#define VERTEX_OFFY 0.2f + +BOOL offsetline(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + x0 = (lx0 + PSXDisplay.CumulOffset.x)+1; + x1 = (lx1 + PSXDisplay.CumulOffset.x)+1; + y0 = (ly0 + PSXDisplay.CumulOffset.y)+1; + y1 = (ly1 + PSXDisplay.CumulOffset.y)+1; + + dx=x1-x0; + dy=y1-y0; + + if(dx>=0) + { + if(dy>=0) + { + px=0.5f; + if(dx>dy) py=-0.5f; + else if(dxdy) px= 0.5f; + else if(dx=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dxdy) py=-0.5f; + else if(dx>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset3(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + + if(CheckCoord3()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset4(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + lx3=(short)(((int)lx3<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + ly3=(short)(((int)ly3<>SIGNSHIFT); + + if(CheckCoord4()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +void offsetST(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + + if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) + lx0+=2048; + + if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) + ly0+=2048; + } + + ly1 = ly0; + ly2 = ly3 = ly0+sprtH; + lx3 = lx0; + lx1 = lx2 = lx0+sprtW; + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; +} + +///////////////////////////////////////////////////////// + +void offsetScreenUpload(long Position) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(Position==-1) + { + long lmdx,lmdy; + + lmdx=xrUploadArea.x0; + lmdy=xrUploadArea.y0; + + lx0-=lmdx; + ly0-=lmdy; + lx1-=lmdx; + ly1-=lmdy; + lx2-=lmdx; + ly2-=lmdy; + lx3-=lmdx; + ly3-=lmdy; + } + else + if(Position) + { + lx0-=PSXDisplay.DisplayPosition.x; + ly0-=PSXDisplay.DisplayPosition.y; + lx1-=PSXDisplay.DisplayPosition.x; + ly1-=PSXDisplay.DisplayPosition.y; + lx2-=PSXDisplay.DisplayPosition.x; + ly2-=PSXDisplay.DisplayPosition.y; + lx3-=PSXDisplay.DisplayPosition.x; + ly3-=PSXDisplay.DisplayPosition.y; + } + else + { + lx0-=PreviousPSXDisplay.DisplayPosition.x; + ly0-=PreviousPSXDisplay.DisplayPosition.y; + lx1-=PreviousPSXDisplay.DisplayPosition.x; + ly1-=PreviousPSXDisplay.DisplayPosition.y; + lx2-=PreviousPSXDisplay.DisplayPosition.x; + ly2-=PreviousPSXDisplay.DisplayPosition.y; + lx3-=PreviousPSXDisplay.DisplayPosition.x; + ly3-=PreviousPSXDisplay.DisplayPosition.y; + } + + vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +///////////////////////////////////////////////////////// + +void offsetBlk(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +//////////////////////////////////////////////////////////////////////// +// texture sow/tow calculations +//////////////////////////////////////////////////////////////////////// + +void assignTextureVRAMWrite(void) +{ +#ifdef OWNSCALE + + vertex[0].sow=0.5f/ ST_FACVRAMX; + vertex[0].tow=0.5f/ ST_FACVRAM; + + vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX; + vertex[1].tow=0.5f/ ST_FACVRAM; + + vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX; + vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM; + + vertex[3].sow=0.5f/ ST_FACVRAMX; + vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM; + +#else + + if(gl_ux[1]==255) + { + vertex[0].sow=(gl_ux[0]*255.99f)/255.0f; + vertex[1].sow=(gl_ux[1]*255.99f)/255.0f; + vertex[2].sow=(gl_ux[2]*255.99f)/255.0f; + vertex[3].sow=(gl_ux[3]*255.99f)/255.0f; + } + else + { + vertex[0].sow=gl_ux[0]; + vertex[1].sow=gl_ux[1]; + vertex[2].sow=gl_ux[2]; + vertex[3].sow=gl_ux[3]; + } + + vertex[0].tow=gl_vy[0]; + vertex[1].tow=gl_vy[1]; + vertex[2].tow=gl_vy[2]; + vertex[3].tow=gl_vy[3]; + +#endif +} + +GLuint gLastTex=0; +GLuint gLastFMode=(GLuint)-1; + +///////////////////////////////////////////////////////// + +void assignTextureSprite(void) +{ + if(bUsingTWin) + { + vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + + vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE; + +#else + + vertex[0].sow=vertex[3].sow=gl_ux[0]; + vertex[1].sow=vertex[2].sow=sSprite_ux2; + vertex[0].tow=vertex[1].tow=gl_vy[0]; + vertex[2].tow=vertex[3].tow=sSprite_vy2; + +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=0) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=0; + } + } + } + + if(usMirror & 0x1000) + { + vertex[0].sow=vertex[1].sow; + vertex[1].sow=vertex[2].sow=vertex[3].sow; + vertex[3].sow=vertex[0].sow; + } + + if(usMirror & 0x2000) + { + vertex[0].tow=vertex[3].tow; + vertex[2].tow=vertex[3].tow=vertex[1].tow; + vertex[1].tow=vertex[0].tow; + } + +} + +///////////////////////////////////////////////////////// + +void assignTexture3(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FACTRI; + vertex[0].tow=(float)gl_vy[0] / ST_FACTRI; + vertex[1].sow=(float)gl_ux[1] / ST_FACTRI; + + vertex[1].tow=(float)gl_vy[1] / ST_FACTRI; + vertex[2].sow=(float)gl_ux[2] / ST_FACTRI; + vertex[2].tow=(float)gl_vy[2] / ST_FACTRI; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<3;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<3;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +///////////////////////////////////////////////////////// + +void assignTexture4(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor; + vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FAC; + vertex[0].tow=(float)gl_vy[0] / ST_FAC; + vertex[1].sow=(float)gl_ux[1] / ST_FAC; + vertex[1].tow=(float)gl_vy[1] / ST_FAC; + vertex[2].sow=(float)gl_ux[2] / ST_FAC; + vertex[2].tow=(float)gl_vy[2] / ST_FAC; + vertex[3].sow=(float)gl_ux[3] / ST_FAC; + vertex[3].tow=(float)gl_vy[3] / ST_FAC; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; + vertex[3].sow=gl_ux[3]; + vertex[3].tow=gl_vy[3]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<4;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<4;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// render pos / buffers +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS +#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom) +#endif + +//////////////////////////////////////////////////////////////////////// +// SetDisplaySettings: "simply" calcs the new drawing area and updates +// the ogl clipping (scissor) + +BOOL bSetClip=FALSE; + +void SetOGLDisplaySettings(BOOL DisplaySet) +{ + static RECT rprev={0,0,0,0}; + static RECT rC ={0,0,0,0}; + static int iOldX=0; + static int iOldY=0; + RECT r;float XS,YS; + + bDisplayNotSet = FALSE; + + //----------------------------------------------------// that's a whole screen upload + if(!DisplaySet) + { + RECT rX; + PSXDisplay.GDrawOffset.x=0; + PSXDisplay.GDrawOffset.y=0; + + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0; + + rprev.left=rprev.left+1; + + rX=rRatioRect; + rX.top=iResY-(rRatioRect.top+rRatioRect.bottom); + + if(bSetClip || !EqualRect(&rC,&rX)) + { + rC=rX; + glScissor(rC.left,rC.top,rC.right,rC.bottom); + bSetClip=FALSE; + } + return; + } + //----------------------------------------------------// + + PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y; + PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0; + + r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y; + + if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y) + { + r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y; + } + + r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x; + + if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x) + { + r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x; + } + + if(!bSetClip && EqualRect(&r,&rprev) && + iOldX == PSXDisplay.DisplayMode.x && + iOldY == PSXDisplay.DisplayMode.y) + return; + + rprev = r; + iOldX = PSXDisplay.DisplayMode.x; + iOldY = PSXDisplay.DisplayMode.y; + + XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + + if(PreviousPSXDisplay.Range.x0) + { + short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1; + + r.left+=PreviousPSXDisplay.Range.x0+1; + + r.right+=PreviousPSXDisplay.Range.x0; + + if(r.left>s) r.left=s; + if(r.right>s) r.right=s; + } + + if(PreviousPSXDisplay.Range.y0) + { + short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1; + + r.top+=PreviousPSXDisplay.Range.y0+1; + r.bottom+=PreviousPSXDisplay.Range.y0; + + if(r.top>s) r.top=s; + if(r.bottom>s) r.bottom=s; + } + + // Set the ClipArea variables to reflect the new screen, + // offset from zero (since it is a new display buffer) + r.left = (int)(((float)(r.left)) *XS); + r.top = (int)(((float)(r.top)) *YS); + r.right = (int)(((float)(r.right + 1))*XS); + r.bottom = (int)(((float)(r.bottom + 1))*YS); + + // Limit clip area to the screen size + if (r.left > iResX) r.left = iResX; + if (r.left < 0) r.left = 0; + if (r.top > iResY) r.top = iResY; + if (r.top < 0) r.top = 0; + if (r.right > iResX) r.right = iResX; + if (r.right < 0) r.right = 0; + if (r.bottom > iResY) r.bottom = iResY; + if (r.bottom < 0) r.bottom = 0; + + r.right -=r.left; + r.bottom-=r.top; + r.top=iResY-(r.top+r.bottom); + + r.left+=rRatioRect.left; + r.top -=rRatioRect.top; + + if(bSetClip || !EqualRect(&r,&rC)) + { + glScissor(r.left,r.top,r.right,r.bottom); + rC=r; + bSetClip=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/gpu-gles/gpuDraw.h b/plugins/gpu-gles/gpuDraw.h new file mode 100644 index 00000000..f5f0426a --- /dev/null +++ b/plugins/gpu-gles/gpuDraw.h @@ -0,0 +1,83 @@ +/*************************************************************************** + draw.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _GL_DRAW_H_ +#define _GL_DRAW_H_ + + +#ifdef __cplusplus + +extern "C" { +#endif + +#include "minimal.h" +#include + +// internally used defines + +#define GPUCOMMAND(x) ((x>>24) & 0xff) +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + +// prototypes + +#ifdef _WINDOWS +BOOL bSetupPixelFormat(HDC hDC); +#endif + +int GLinitialize(); +void GLcleanup(); +#ifdef _WINDOWS +BOOL offset2(void); +BOOL offset3(void); +BOOL offset4(void); +BOOL offsetline(void); +#else +unsigned short offset2(void); +unsigned short offset3(void); +unsigned short offset4(void); +unsigned short offsetline(void); +#endif +void offsetST(void); +void offsetBlk(void); +void offsetScreenUpload(long Position); +void assignTexture3(void); +void assignTexture4(void); +void assignTextureSprite(void); +void assignTextureVRAMWrite(void); +void SetOGLDisplaySettings (unsigned short DisplaySet); +void ReadConfig(void); +void WriteConfig(void); +void SetExtGLFuncs(void); +/////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif // _GL_DRAW_H_ diff --git a/plugins/gpu-gles/gpuExternals.h b/plugins/gpu-gles/gpuExternals.h new file mode 100644 index 00000000..f24c31ad --- /dev/null +++ b/plugins/gpu-gles/gpuExternals.h @@ -0,0 +1,570 @@ +/*************************************************************************** + external.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////////////////////////// + +#ifndef __GPU_EX__ +#define __GPU_EX__ + +#ifdef __cplusplus +extern "C" { +#endif +#define _GPU_API_ +#ifndef _WINDOWS +#ifdef __NANOGL__ +#include +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#include // for opengl es types +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#endif + +#ifdef MAEMO_CHANGES + #include "../psxCommon.h" +#else + #include "psxCommon.h" +#endif + +#ifdef __NANOGL__ +#define glTexParameteri(x,y,z) glTexParameterf(x,y,z) +#define glAlphaFuncx(x,y) glAlphaFunc(x,y) +#ifndef APIENTRY +#define APIENTRY +#endif +extern void ( APIENTRY * glPixelStorei )(GLenum pname, GLint param); +#endif + + +#define MIRROR_TEST 1 + +///////////////////////////////////////////////////////////////////////////// + +#define SCISSOR_TEST 1 + +///////////////////////////////////////////////////////////////////////////// + +// for own sow/tow scaling +#define OWNSCALE 1 + +///////////////////////////////////////////////////////////////////////////// + +#define CLUTUSED 0x80000000 +//glColor4ubv(x.c.col) +#define SETCOL(x) if(x.c.lcol!=ulOLDCOL) {ulOLDCOL=x.c.lcol;glColor4ub(x.c.col[0],x.c.col[1],x.c.col[2],x.c.col[3]);} +//#define SETPCOL(x) if(x->c.lcol!=ulOLDCOL) {ulOLDCOL=x->c.lcol;glColor4ub(x->c.col[0],x->c.col[1],x->c.col[2],x->c.col[3]);} + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define SIGNSHIFT 21 +#define CHKMAX_X 1024 +#define CHKMAX_Y 512 + +///////////////////////////////////////////////////////////////////////////// + +// GPU STATUS REGISTER bit values (c) Lewpy + +#define DR_NORMAL 0 +#define DR_VRAMTRANSFER 1 + +#define GPUSTATUS_ODDLINES 0x80000000 +#define GPUSTATUS_DMABITS 0x60000000 // Two bits +#define GPUSTATUS_READYFORCOMMANDS 0x10000000 +#define GPUSTATUS_READYFORVRAM 0x08000000 +#define GPUSTATUS_IDLE 0x04000000 +#define GPUSTATUS_DISPLAYDISABLED 0x00800000 +#define GPUSTATUS_INTERLACED 0x00400000 +#define GPUSTATUS_RGB24 0x00200000 +#define GPUSTATUS_PAL 0x00100000 +#define GPUSTATUS_DOUBLEHEIGHT 0x00080000 +#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits +#define GPUSTATUS_MASKENABLED 0x00001000 +#define GPUSTATUS_MASKDRAWN 0x00000800 +#define GPUSTATUS_DRAWINGALLOWED 0x00000400 +#define GPUSTATUS_DITHER 0x00000200 + +#define STATUSREG lGPUstatusRet + +#define GPUIsBusy (STATUSREG &= ~GPUSTATUS_IDLE) +#define GPUIsIdle (STATUSREG |= GPUSTATUS_IDLE) + +#define GPUIsNotReadyForCommands (STATUSREG &= ~GPUSTATUS_READYFORCOMMANDS) +#define GPUIsReadyForCommands (STATUSREG |= GPUSTATUS_READYFORCOMMANDS) + +///////////////////////////////////////////////////////////////////////////// + +#define KEY_RESETTEXSTORE 1 +#define KEY_SHOWFPS 2 +#define KEY_RESETOPAQUE 4 +#define KEY_RESETDITHER 8 +#define KEY_RESETFILTER 16 +#define KEY_RESETADVBLEND 32 +#define KEY_BLACKWHITE 64 +#define KEY_TOGGLEFBTEXTURE 128 +#define KEY_STEPDOWN 256 +#define KEY_TOGGLEFBREAD 512 + +///////////////////////////////////////////////////////////////////////////// +// Linux is missing some stuff, eh? ;) + +#ifndef _WINDOWS +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef BOOL +#define BOOL unsigned short +#endif +#ifndef bool +#define bool unsigned short +#endif +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define DWORD unsigned long + +typedef struct RECTTAG +{ + int left; + int top; + int right; + int bottom; +}RECT; + +#endif + +///////////////////////////////////////////////////////////////////////////// + +typedef struct VRAMLOADTAG +{ + short x; + short y; + short Width; + short Height; + short RowsRemaining; + short ColsRemaining; + unsigned short *ImagePtr; +} VRAMLoad_t; + +typedef struct PSXPOINTTAG +{ + long x; + long y; +} PSXPoint_t; + +typedef struct PSXSPOINTTAG +{ + short x; + short y; +} PSXSPoint_t; + +typedef struct PSXRECTTAG +{ + short x0; + short x1; + short y0; + short y1; +} PSXRect_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct TWINTAG +{ + PSXRect_t Position; + PSXRect_t OPosition; + PSXPoint_t TextureSize; + float UScaleFactor; + float VScaleFactor; +} TWin_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct PSXDISPLAYTAG +{ + PSXPoint_t DisplayModeNew; + PSXPoint_t DisplayMode; + PSXPoint_t DisplayPosition; + PSXPoint_t DisplayEnd; + + long Double; + long Height; + long PAL; + long InterlacedNew; + long Interlaced; + long InterlacedTest; + long RGB24New; + long RGB24; + PSXSPoint_t DrawOffset; + PSXRect_t DrawArea; + PSXPoint_t GDrawOffset; + PSXPoint_t CumulOffset; + long Disabled; + PSXRect_t Range; +} PSXDisplay_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct OGLVertexTag +{ + GLfloat x; + GLfloat y; + GLfloat z; + + GLfloat sow; + GLfloat tow; + + union +COLTAG + { + u8 col[4]; + unsigned long lcol; + } c; + +} OGLVertex; + +typedef union EXShortTag +{ + u8 c[2]; + unsigned short s; +} EXShort; + +typedef union EXLongTag +{ + u8 c[4]; + unsigned long l; + EXShort s[2]; +} EXLong; + + +///////////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +extern HINSTANCE hInst; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_DRAW + +extern int iResX; +extern int iResY; +extern BOOL bKeepRatio; +extern RECT rRatioRect; +extern BOOL bOpaquePass; +extern BOOL bAdvancedBlend; + +//extern PFNGLBLENDEQU glBlendEquationEXTEx; +//extern PFNGLCOLORTABLEEXT glColorTableEXTEx; + +extern u8 gl_ux[8]; +extern u8 gl_vy[8]; +extern OGLVertex vertex[4]; +extern short sprtY,sprtX,sprtH,sprtW; +#ifdef _WINDOWS +extern HWND hWWindow; +#endif +extern BOOL bIsFirstFrame; +extern int iWinSize; +extern int iZBufferDepth; +extern GLbitfield uiBufferBits; +extern int iUseMask; +extern int iSetMask; +extern int iDepthFunc; +extern BOOL bCheckMask; +extern unsigned short sSetMask; +extern unsigned long lSetMask; +extern BOOL bSetClip; +extern GLuint gTexScanName; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_SOFT + +extern long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +extern long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; +extern short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; +extern short g_m1; +extern short g_m2; +extern short g_m3; +extern short DrawSemiTrans; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_PRIMDRAW + +extern BOOL bNeedUploadTest; +extern BOOL bNeedUploadAfter; +extern BOOL bTexEnabled; +extern BOOL bBlendEnable; +extern BOOL bDrawDither; +extern int iFilterType; +extern BOOL bFullVRam; +extern BOOL bUseMultiPass; +extern int iOffscreenDrawing; +extern BOOL bOldSmoothShaded; +extern BOOL bUsingTWin; +extern BOOL bUsingMovie; +extern PSXRect_t xrMovieArea; +extern PSXRect_t xrUploadArea; +extern PSXRect_t xrUploadAreaIL; +extern PSXRect_t xrUploadAreaRGB24; +extern GLuint gTexName; +extern BOOL bDrawNonShaded; +extern BOOL bDrawMultiPass; +extern GLubyte ubGloColAlpha; +extern GLubyte ubGloAlpha; +extern short sSprite_ux2; +extern short sSprite_vy2; +extern BOOL bRenderFrontBuffer; +extern unsigned long ulOLDCOL; +extern unsigned long ulClutID; +extern void (*primTableJ[256])(u8 *); +extern void (*primTableSkip[256])(u8 *); +extern unsigned short usMirror; +extern unsigned long dwCfgFixes; +extern unsigned long dwActFixes; +extern unsigned long dwEmuFixes; +extern BOOL bUseFixes; +extern int iSpriteTex; +extern int iDrawnSomething; + +extern long drawX; +extern long drawY; +extern long drawW; +extern long drawH; +extern short sxmin; +extern short sxmax; +extern short symin; +extern short symax; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_TEXTURE + +extern u8 ubOpaqueDraw; +extern GLint giWantedRGBA; +extern GLint giWantedFMT; +extern GLint giWantedTYPE; +extern void (*LoadSubTexFn) (int,int,short,short); +extern long GlobalTexturePage; +extern unsigned long (*TCF[]) (unsigned long); +extern unsigned short (*PTCF[]) (unsigned short); +extern unsigned long (*PalTexturedColourFn) (unsigned long); +extern BOOL bUseFastMdec; +extern BOOL bUse15bitMdec; +extern int iFrameTexType; +extern int iFrameReadType; +extern int iClampType; +extern int iSortTexCnt; +extern BOOL bFakeFrontBuffer; +extern GLuint gTexFrameName; +extern GLuint gTexBlurName; +extern int iVRamSize; +extern int iTexGarbageCollection; +extern int iFTexA; +extern int iFTexB; +extern BOOL bIgnoreNextTile; + + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_GPU + +extern VRAMLoad_t VRAMWrite; +extern VRAMLoad_t VRAMRead; +extern int iDataWriteMode; +extern int iDataReadMode; +extern int iColDepth; +extern BOOL bChangeRes; +extern BOOL bWindowMode; +extern s8 szDispBuf[]; +extern s8 szGPUKeys[]; +extern PSXDisplay_t PSXDisplay; +extern PSXDisplay_t PreviousPSXDisplay; +//extern unsigned long ulKeybits; +extern TWin_t TWin; +extern BOOL bDisplayNotSet; +extern long lGPUstatusRet; +extern short imageX0,imageX1; +extern short imageY0,imageY1; +extern long lClearOnSwap,lClearOnSwapColor; +extern u8 * psxVub; +extern s8 * psxVsb; +extern unsigned short * psxVuw; +extern signed short * psxVsw; +extern unsigned long * psxVul; +extern signed long * psxVsl; +extern GLfloat gl_z; +extern BOOL bNeedRGB24Update; +extern BOOL bChangeWinMode; +extern GLuint uiScanLine; +extern int iUseScanLines; +extern long lSelectedSlot; +extern int iScanBlend; +extern BOOL bInitCap; +extern int iBlurBuffer; +extern int iLastRGB24; +extern int iRenderFVR; +extern int iNoScreenSaver; +extern unsigned long ulGPUInfoVals[]; +extern BOOL bNeedInterlaceUpdate; +extern BOOL bNeedWriteUpload; +extern BOOL bSkipNextFrame; + + +#ifndef _WINDOWS +extern int bFullScreen; +#endif + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_MENU + +//extern unsigned long dwCoreFlags; +extern GLuint gTexPicName; +//extern PSXPoint_t ptCursorPoint[]; +//extern unsigned short usCursorActive; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_CFG + +#ifndef _WINDOWS +extern s8 * pConfigFile; +#endif + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_FPS + +extern BOOL bUseFrameLimit; +extern BOOL bUseFrameSkip; +extern float fFrameRate; +extern float fFrameRateHz; +extern int iFrameLimit; +extern float fps_skip; +extern float fps_cur; + +#endif + +//-----------------------------------------------------// + +typedef struct { +u8 r; +u8 g; +u8 b; +u8 a; +} Vec4f; + +/**/ +typedef struct { +float x; +float y; +float z; +} Vec3f; + +typedef struct { +float x; +float y; +} Vec2f; + +/* +typedef struct { +int x; +int y; +int z; +} Vec3f; + +typedef struct { +int x; +int y; +} Vec2f; +/**/ + +typedef struct { + Vec3f xyz; + Vec2f st; +} Vertex; + +typedef struct { + Vec3f xyz; + Vec2f st; + Vec4f rgba; +} Vertex2; + +#ifndef _IN_KEY + +//extern unsigned long ulKeybits; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_ZN + +extern unsigned long dwGPUVersion; +extern int iGPUHeight; +extern int iGPUHeightMask; +extern int GlobalTextIL; +extern int iTileCheat; + +#endif + +#ifdef __cplusplus +} +#endif + + +#endif + +//-----------------------------------------------------// diff --git a/plugins/gpu-gles/gpuFps.c b/plugins/gpu-gles/gpuFps.c new file mode 100644 index 00000000..1012ecbe --- /dev/null +++ b/plugins/gpu-gles/gpuFps.c @@ -0,0 +1,991 @@ +/*************************************************************************** + fps.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifdef _WINDOWS +#include "Stdafx.h" +#include "Externals.h" +#include "plugin.h" +#include "Fps.h" +#include "Prim.h" +#else +#include "gpuStdafx.h" +#include "gpuExternals.h" +//#include "plugins.h" +#include "gpuFps.h" +#include "gpuPrim.h" +#endif + +#define _IN_FPS + +#define CALLBACK + +//////////////////////////////////////////////////////////////////////// +// FPS stuff +//////////////////////////////////////////////////////////////////////// +#ifdef _WINDOWS +LARGE_INTEGER liCPUFrequency; +#endif + +//////////////////////////////////////////////////////////////////////// +// FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +BOOL bIsPerformanceCounter; +float fFrameRateHz; +DWORD dwFrameRateTicks; +float fFrameRate; +int iFrameLimit; +BOOL bUseFrameLimit; +BOOL bUseFrameSkip; +DWORD dwLaceCnt; + +BOOL bInitCap; +float fps_skip; +float fps_cur; + +#ifdef _WINDOWS + +void FrameCap (void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + static BOOL SkipNextWait = FALSE; + BOOL Waiting = TRUE; + + //--------------------------------------------------------- + // init some static vars... + // bInitCap is TRUE on startup and everytime the user + // is toggling the frame limit + //--------------------------------------------------------- + + if(bInitCap) + { + bInitCap=FALSE; + if (bIsPerformanceCounter) + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + TicksToWait=0; + return; + } + + //--------------------------------------------------------- + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = dwFrameRateTicks+TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + + lastticks=curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = dwFrameRateTicks; + } + } + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + lastticks = curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + if(bIsPerformanceCounter) // -> now we calc the time of the last drawn frame + the time we spent skipping + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + } + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + if(bIsPerformanceCounter) // -> ok, start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + if(bIsPerformanceCounter) // -> we store the start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + if(bIsPerformanceCounter) // get the current time (we are now at the end of one drawn frame) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + } + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,(((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update) +1.0f)); + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,((float)1000/(float)_ticks_since_last_update+1.0f)); + + lastticks = curticks; + } + + if(bUseFrameSkip && bUseFrameLimit) + { + fpsskip_tck += _ticks_since_last_update; + + if(++fpsskip_cnt==2) + { + if(bIsPerformanceCounter) + fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f; + else + fps_skip = (float)2000/(float)fpsskip_tck; + + fps_skip +=6.0f; + + fpsskip_cnt = 0; + fpsskip_tck = 1; + } + } + + fps_tck += _ticks_since_last_update; + + if(++fps_cnt==10) + { + if(bIsPerformanceCounter) + fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f; + else + fps_cur = (float)10000/(float)fps_tck; + + fps_cnt = 0; + fps_tck = 1; + + if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +//////////////////////////////////////////////////////////////////////// +// PC FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +void PCFrameCap(void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + BOOL Waiting = TRUE; + + while (Waiting) + { + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //------------------------------------------------// + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz); + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (1000 / (DWORD)fFrameRateHz); + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void PCcalcfps(void) +{ + static DWORD curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + float CurrentFPS=0; + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart; + + //--------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(_ticks_since_last_update) + { + CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update); + } + else CurrentFPS = 0; + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + if(_ticks_since_last_update=curticks-lastticks) + CurrentFPS=(float)1000/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + } + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +//////////////////////////////////////////////////////////////////////// + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + } +} + +//////////////////////////////////////////////////////////////////////// + +void InitFrameCap(void) // inits cpu frequency info (on gpu startup) +{ + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void ReInitFrameCap(void) +{ + BOOL bOldPerformanceCounter=bIsPerformanceCounter; // store curr timer mode + + if(dwActFixes&0x10000) // check game fix... high performance counters are bad on some mb chipsets + bIsPerformanceCounter=FALSE; + else + { + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; + } + + if(bOldPerformanceCounter!=bIsPerformanceCounter) // changed? + { + bInitCap = TRUE; + SetAutoFrameCap(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetFrameRateConfig(void) +{ + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); +} + +//////////////////////////////////////////////////////////////////////// + +// LINUX --------------------------------------------- + +#else + +#define TIMEBASE 100000 + +// hehehe... using same func name as with win32 ;) wow, are we genius ;) +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 100000 + tv.tv_usec/10; // to do that in linux, but at least it works +} + +void FrameCap(void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if((_ticks_since_last_update > TicksToWait) || + (curticks dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_updatefFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +void PCFrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz); + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void PCcalcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + float CurrentFPS=0; + + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + if(_ticks_since_last_update) + CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +//////////////////////////////////////////////////////////////////////// + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetFrameRateConfig(void) +{ + if(!fFrameRate) fFrameRate=200.0f; + + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + + if(iFrameLimit==2) SetAutoFrameCap(); +} + +//////////////////////////////////////////////////////////////////////// + +void InitFrameCap(void) +{ + // nothing on linux +} + +void ReInitFrameCap(void) +{ + // nothing on linux +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync) +{ + if(bUseFrameSkip) + { + if(!(dwActFixes&0x100)) + { + dwLaceCnt++; // -> and store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && bUseFrameLimit) + { + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(bUseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // -> non-skipping mode: + { + if(bUseFrameLimit) FrameCap(); + calcfps(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way +{ + bInitCap = TRUE; + + if(option==1) // emu says: limit + { + bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2; + SetAutoFrameCap(); + } + else // emu says: no limit + { + bUseFrameLimit=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// diff --git a/plugins/gpu-gles/gpuFps.h b/plugins/gpu-gles/gpuFps.h new file mode 100644 index 00000000..a44a05fc --- /dev/null +++ b/plugins/gpu-gles/gpuFps.h @@ -0,0 +1,66 @@ +#ifndef __GPU_FPS__ +#define __GPU_FPS__ + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + fps.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +extern BOOL bIsPerformanceCounter; +extern float fFrameRateHz; +extern DWORD dwFrameRateTicks; +extern float fFrameRate; +extern int iFrameLimit; +extern BOOL bUseFrameLimit; +extern BOOL bUseFrameSkip; +extern DWORD dwLaceCnt; + +extern BOOL bInitCap; +extern float fps_skip; +extern float fps_cur; + + +void InitFrameCap(void); +void SetFrameRateConfig(void); +void PCFrameCap(void); +void PCcalcfps(void); +void FrameSkip(void); +void CheckFrameRate(void); +void ReInitFrameCap(void); +void SetAutoFrameCap(void); +#ifndef _WINDOWS +unsigned long timeGetTime(); +#endif + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/plugins/gpu-gles/gpuPlugin.c b/plugins/gpu-gles/gpuPlugin.c new file mode 100644 index 00000000..07f158c3 --- /dev/null +++ b/plugins/gpu-gles/gpuPlugin.c @@ -0,0 +1,2960 @@ +/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +//#include "gpuStdafx.h" + +//#include + +#define _IN_GPU + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#include +#include +#include +#include + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#include "fps.h" +#include "resource.h" +#else +#include +#include +#include +#include +#include "gpuExternals.h" +#include "gpuPlugin.h" +#include "gpuDraw.h" +#include "gpuTexture.h" +#include "gpuFps.h" +#include "gpuPrim.h" + +//#include "NoPic.h" + +#include "gpuStdafx.h" +#endif + +extern void ProcessEvents(); + +short g_m1=255,g_m2=255,g_m3=255; +short DrawSemiTrans=FALSE; +short Ymin; +short Ymax; + +short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords +long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; + +unsigned long dwGPUVersion=0; +int iGPUHeight=512; +int iGPUHeightMask=511; +int GlobalTextIL=0; +int iTileCheat=0; + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +u8 *psxVSecure; +u8 *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +unsigned long *psxVul; +signed long *psxVsl; + +// macro for easy access to packet information +#define GPUCOMMAND(x) ((x>>24) & 0xff) + +GLfloat gl_z=0.0f; +BOOL bNeedInterlaceUpdate=FALSE; +BOOL bNeedRGB24Update=FALSE; +BOOL bChangeWinMode=FALSE; + +#ifdef _WINDOWS +extern HGLRC GLCONTEXT; +#endif + +unsigned long ulStatusControl[256]; + +//////////////////////////////////////////////////////////////////////// +// global GPU vars +//////////////////////////////////////////////////////////////////////// + +static long GPUdataRet; +long lGPUstatusRet; +s8 szDispBuf[64]; + +static unsigned long gpuDataM[256]; +static u8 gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +int iDataWriteMode; +int iDataReadMode; + +long lClearOnSwap; +long lClearOnSwapColor; +BOOL bSkipNextFrame = FALSE; +int iColDepth; +BOOL bChangeRes; +BOOL bWindowMode; +int iWinSize; + +// possible psx display widths +short dispWidths[8] = {256,320,512,640,368,384,512,640}; + +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +TWin_t TWin; +short imageX0,imageX1; +short imageY0,imageY1; +BOOL bDisplayNotSet = TRUE; +GLuint uiScanLine=0; +int iUseScanLines=0; +long lSelectedSlot=0; +u8 * pGfxCardScreen=0; +int iBlurBuffer=0; +int iScanBlend=0; +int iRenderFVR=0; +int iNoScreenSaver=0; +unsigned long ulGPUInfoVals[16]; +int iFakePrimBusy = 0; +int iRumbleVal = 0; +int iRumbleTime = 0; + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +s8 * CALLBACK PSEgetLibName(void) +{ + return "name"; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return 1; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return 1<<16|1<<8|1; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// snapshot funcs (saves screen to bitmap / text infos into file) +//////////////////////////////////////////////////////////////////////// + +void ResizeWindow() +{ + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + +#ifndef OWNSCALE + glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale" + glLoadIdentity(); + glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack +#endif + + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + if (bKeepRatio) + SetAspectRatio(); +} + +s8 * GetConfigInfos(int hW) +{ +#ifdef _WINDOWS + HDC hdc;HGLRC hglrc; +#endif + s8 szO[2][4]={"off","on "}; + s8 szTxt[256]; + s8 * pB=(s8 *)malloc(32767); +/* + if(!pB) return NULL; + *pB=0; + //----------------------------------------------------// + strcat(pB,szTxt); + strcat(pB,szTxt); +#ifdef _WINDOWS + if(hW) + { + hdc = GetDC(hW); + bSetupPixelFormat(hdc); + hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + } +#endif + sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); + strcat(pB,szTxt); + sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); + strcat(pB,szTxt); + sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); + strcat(pB,szTxt); + //strcat(pB,(s8 *)glGetString(GL_EXTENSIONS)); + //strcat(pB,"\r\n\r\n"); + +#ifdef _WINDOWS + if(hW) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hW,hdc); + } + //----------------------------------------------------// +#endif + if(hW && bWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + strcat(pB,szTxt); + if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); + else + { + sprintf(szTxt,"Fullscreen "); + strcat(pB,szTxt); + if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); + else sprintf(szTxt,"- NO desktop changing\r\n"); + } + strcat(pB,szTxt); + +// if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); +// else strcpy(szTxt,"- V-Sync: Driver\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); + strcat(pB,szTxt); + //----------------------------------------------------// + strcpy(szTxt,"Textures:\r\n- "); +/*! if(iTexQuality==0) strcat(szTxt,"Default"); + else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); + else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); + else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); + else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); + if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); + if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); + else strcat(szTxt,"NOT supported\r\n"); + } + else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); + strcat(pB,szTxt); + sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); + strcat(pB,szTxt); + } + !*/ + /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); + if(!hW) + sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); + else strcat(szTxt,"\r\n\r\n"); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); + strcat(pB,szTxt); + if(iFrameLimit==2) + strcpy(szTxt,"- FPS limit: Auto\r\n\r\n"); + else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); + if(!hW && iFrameTexType==2) + { + if(gTexFrameName) strcat(szTxt," - texture created\r\n"); + else strcat(szTxt," - not used yet\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); + strcat(pB,szTxt); +// sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); + strcat(pB,szTxt); + sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); + strcat(pB,szTxt); + //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); + //if(!hW && bAdvancedBlend) +// { +// if(bGLBlend) strcat(szTxt," (hardware)\r\n"); +// else strcat(szTxt," (software)\r\n"); +// } + strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + + if(!hW) + { + strcpy(szTxt,"- Subtractive blending: "); +// if(glBlendEquationEXTEx) +// { +// if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); +// else strcat(szTxt,"activated"); +// } + strcat(szTxt," NOT supported!"); + strcat(szTxt,"\r\n\r\n"); + } + else strcpy(szTxt,"\r\n"); + + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); + strcat(pB,szTxt); + if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); + else strcpy(szTxt,"\r\n"); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); +// fwrite(szTxt,lstrlen(szTxt),1,txtfile); + sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); + strcat(pB,szTxt); + sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); + strcat(pB,szTxt); + if(!hW && iBlurBuffer) + { + if(gTexBlurName) strcat(pB," - supported\r\n"); + else strcat(pB," - not supported\r\n"); + } + else strcat(pB,"\r\n"); + sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// +*/ return pB; +} + +//////////////////////////////////////////////////////////////////////// +// save text infos to file +//////////////////////////////////////////////////////////////////////// + +void DoTextSnapShot(int iNum) +{ +} + +//////////////////////////////////////////////////////////////////////// +// saves screen bitmap to file +//////////////////////////////////////////////////////////////////////// + +void DoSnapShot(void) +{ +} + +#ifdef _WINDOWS +void CALLBACK GPUmakeSnapshot(void) +#else +void CALLBACK GPU_makeSnapshot(void) +#endif +{ + //bSnapShot = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// GPU INIT... here starts it all (first func called by emu) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUinit() +#else +long CALLBACK GPU_init() +#endif +{ +memset(ulStatusControl,0,256*sizeof(unsigned long)); + +#ifdef _WINDOWS +iResX=240;iResY=320; +#endif +bChangeRes=FALSE; +#ifdef _WINDOWS +bWindowMode=TRUE; +#else +bWindowMode=FALSE; +#endif +#ifdef _WINDOWS +iWinSize=MAKELONG(iResX,iResY); +#endif + +bKeepRatio = TRUE; +// different ways of accessing PSX VRAM + +psxVSecure=(u8 *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security +if(!psxVSecure) return -1; + +psxVub=psxVSecure+512*1024; // security offset into double sized psx vram! +psxVsb=(signed char *)psxVub; +psxVsw=(signed short *)psxVub; +psxVsl=(signed long *)psxVub; +psxVuw=(unsigned short *)psxVub; +psxVul=(unsigned long *)psxVub; + +psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + +memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); +memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long)); + +InitFrameCap(); // init frame rate stuff + +PSXDisplay.RGB24 = 0; // init vars +PreviousPSXDisplay.RGB24= 0; +PSXDisplay.Interlaced = 0; +PSXDisplay.InterlacedTest=0; +PSXDisplay.DrawOffset.x = 0; +PSXDisplay.DrawOffset.y = 0; +PSXDisplay.DrawArea.x0 = 0; +PSXDisplay.DrawArea.y0 = 0; +PSXDisplay.DrawArea.x1 = 320; +PSXDisplay.DrawArea.y1 = 240; +PSXDisplay.DisplayMode.x= 320; +PSXDisplay.DisplayMode.y= 240; +PSXDisplay.Disabled = FALSE; +PreviousPSXDisplay.Range.x0 =0; +PreviousPSXDisplay.Range.x1 =0; +PreviousPSXDisplay.Range.y0 =0; +PreviousPSXDisplay.Range.y1 =0; +PSXDisplay.Range.x0=0; +PSXDisplay.Range.x1=0; +PSXDisplay.Range.y0=0; +PSXDisplay.Range.y1=0; +PreviousPSXDisplay.DisplayPosition.x = 1; +PreviousPSXDisplay.DisplayPosition.y = 1; +PSXDisplay.DisplayPosition.x = 1; +PSXDisplay.DisplayPosition.y = 1; +PreviousPSXDisplay.DisplayModeNew.y=0; +PSXDisplay.Double=1; +GPUdataRet=0x400; + +PSXDisplay.DisplayModeNew.x=0; +PSXDisplay.DisplayModeNew.y=0; + +//PreviousPSXDisplay.Height = PSXDisplay.Height = 239; + +iDataWriteMode = DR_NORMAL; + +// Reset transfer values, to prevent mis-transfer of data +memset(&VRAMWrite,0,sizeof(VRAMLoad_t)); +memset(&VRAMRead,0,sizeof(VRAMLoad_t)); + +// device initialised already ! +//lGPUstatusRet = 0x74000000; + +STATUSREG = 0x14802000; +GPUIsIdle; +GPUIsReadyForCommands; + +return 0; +} + + +//////////////////////////////////////////////////////////////////////// +// GPU OPEN: funcs to open up the gpu display (Windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +void ChangeDesktop() // change destop resolution +{ + DEVMODE dv;long lRes,iTry=0; + + while(iTry<10) // keep on hammering... + { + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + dv.dmBitsPerPel=iColDepth; + dv.dmPelsWidth=iResX; + dv.dmPelsHeight=iResY; + + dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil + + if(lRes==DISP_CHANGE_SUCCESSFUL) return; + iTry++;Sleep(10); + } +} + +//////////////////////////////////////////////////////////////////////// +// OPEN interface func: attention! +// some emus are calling this func in their main Window thread, +// but all other interface funcs (to draw stuff) in a different thread! +// that's a problem, since OGL is thread safe! Therefore we cannot +// initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE" +// flag, to initialize OGL on the first real draw call. +// btw, we also call this open func ourselfes, each time when the user +// is changing between fullscreen/window mode (ENTER key) +// btw part 2: in windows the plugin gets the window handle from the +// main emu, and doesn't create it's own window (if it would do it, +// some PAD or SPU plugins would not work anymore) +//////////////////////////////////////////////////////////////////////// + +HMENU hPSEMenu=NULL; + +long CALLBACK GPUopen(HWND hwndGPU) +#else +long CALLBACK GPU_open(int hwndGPU) +#endif +{ + #ifdef _WINDOWS + HDC hdc;RECT r;DEVMODE dv; + + hWWindow = hwndGPU; // store hwnd globally + #endif + // InitKeyHandler(); // init key handler (subclass window) + + + + + + #ifdef _WINDOWS + iResX=240;iResY=320; + #endif + iColDepth=32; + bChangeRes=FALSE; + #ifdef _WINDOWS + bWindowMode=TRUE; + #else + bWindowMode=FALSE; + #endif + bFullVRam=FALSE; + iFilterType=0; + // bAdvancedBlend=FALSE; + bDrawDither=FALSE; + // bUseLines=FALSE; + bUseFrameLimit=FALSE; + bUseFrameSkip=FALSE; + iFrameLimit=0; + fFrameRate=50.0f; + iOffscreenDrawing=0; + //bOpaquePass=FALSE; + //bUseAntiAlias=FALSE; + //iTexQuality=0; + #ifdef _WINDOWS + iWinSize=MAKELONG(iResX,iResY); + #endif + iUseMask=0; + iZBufferDepth=0; + bUseFastMdec=FALSE; + bUse15bitMdec=FALSE; + dwCfgFixes=0; + bUseFixes=FALSE; + // iUseScanLines=0; + iFrameTexType=0; + iFrameReadType=0; + //iShowFPS=0; + bKeepRatio=TRUE; + iScanBlend=0; + iVRamSize=0; + iTexGarbageCollection=0; + iBlurBuffer=0; + //iHiResTextures=0; + iNoScreenSaver=0; + //iForceVSync=0; + + + +#ifdef _WINDOWS + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); +#endif + bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! + +#ifdef _WINDOWS + if(bWindowMode) // win mode? + { + DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) + dw&=~WS_THICKFRAME; + dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; + SetWindowLong(hWWindow, GWL_STYLE, dw); + + hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + + iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); + ShowWindow(hWWindow,SW_SHOWNORMAL); + + MoveWindow(hWWindow, // -> center wnd + GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, + GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, + iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, + iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, + TRUE); + UpdateWindow(hWWindow); // -> let windows do some update + + if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info + iColDepth=dv.dmBitsPerPel; + } + else // fullscreen mode: + { + if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution + dv.dmPelsWidth !=(unsigned int)iResX || + dv.dmPelsHeight!=(unsigned int)iResY) + bChangeRes=TRUE; else bChangeRes=FALSE; + + if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') + + SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) + + hPSEMenu=GetMenu(hWWindow); // -> hide menu + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode + } +#endif + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + +#ifdef _WINDOWS + r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized + hdc = GetDC(hWWindow); + FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); + bSetupPixelFormat(hdc); + ReleaseDC(hWWindow,hdc); +#endif + bDisplayNotSet = TRUE; + bSetClip=TRUE; + + SetFixes(); // setup game fixes + + InitializeTextureStore(); // init texture mem + +// lGPUstatusRet = 0x74000000; + +// with some emus, we could do the OGL init right here... oh my +// if(bIsFirstFrame) GLinitialize(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// close +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUclose() // WINDOWS CLOSE +{ +// ExitKeyHandler(); + + GLcleanup(); // close OGL + + if(bChangeRes) // change res back + ChangeDisplaySettings(NULL,0); + + if(hPSEMenu) // set menu again + SetMenu(hWWindow,hPSEMenu); + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + +// if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again + + return 0; +} + +#else + +long GPU_close() // LINUX CLOSE +{ + GLcleanup(); // close OGL + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + +// osd_close_display(); // destroy display + + return 0; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff... last function called from emu +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUshutdown() +#else +long CALLBACK GPU_shutdown() +#endif +{ + if(psxVSecure) free(psxVSecure); // kill emulated vram memory + psxVSecure=0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// paint it black: simple func to clean up optical border garbage +//////////////////////////////////////////////////////////////////////// + +void PaintBlackBorders(void) +{ + short s; + + glDisable(GL_SCISSOR_TEST); + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + glDisable(GL_ALPHA_TEST); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// helper to draw scanlines +//////////////////////////////////////////////////////////////////////// + +__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + +} + +//////////////////////////////////////////////////////////////////////// +// scanlines +//////////////////////////////////////////////////////////////////////// + +void SetScanLines(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers)... called in interlaced mode on +// every emulated vsync, otherwise whenever the displayed screen region +// has been changed +//////////////////////////////////////////////////////////////////////// + +int iLastRGB24=0; // special vars for checking when to skip two display updates +int iSkipTwo=0; +void GPU_vSinc(void){ +updateDisplay(); +} +void updateDisplay(void) // UPDATE DISPLAY +{ +BOOL bBlur=FALSE; + +#ifdef _WINDOWS +HDC hdc=GetDC(hWWindow); // windows: +wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again +#endif + +bFakeFrontBuffer=FALSE; +bRenderFrontBuffer=FALSE; + +if(iRenderFVR) // frame buffer read fix mode still active? + { + iRenderFVR--; // -> if some frames in a row without read access: turn off mode + if(!iRenderFVR) bFullVRam=FALSE; + } + +if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check + { + iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes + } +iLastRGB24=0; + +if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? + { + PrepareFullScreenUpload(-1); + UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram + bNeedUploadTest=FALSE; + bNeedInterlaceUpdate=FALSE; + bNeedUploadAfter=FALSE; + bNeedRGB24Update=FALSE; + } +else +if(bNeedInterlaceUpdate) // smaller upload? + { + bNeedInterlaceUpdate=FALSE; + xrUploadArea=xrUploadAreaIL; // -> upload this rect + UploadScreen(TRUE); + } + +if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 + +if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + +if(PSXDisplay.Disabled) // display disabled? + { + // moved here + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,128); // -> clear whole backbuffer + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + gl_z=0.0f; + bDisplayNotSet = TRUE; + } + +if(iSkipTwo) // we are in skipping mood? + { + iSkipTwo--; + iDrawnSomething=0; // -> simply lie about something drawn + } + +//if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? +// {BlurBackBuffer();bBlur=TRUE;} // -> blur it + +// if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it + +// if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em + +if(dwActFixes&128) // special FPS limitation mode? + { + if(bUseFrameLimit) PCFrameCap(); // -> ok, do it +// if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + +// if(gTexPicName) DisplayPic(); // some gpu info picture active? display it + +// if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) + +// if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? + { +// sprintf(szDispBuf,"%06.1f",fps_cur); +// DisplayText(); // -> show it + } + +//----------------------------------------------------// +// main buffer swapping (well, or skip it) + +if(bUseFrameSkip) // frame skipping active ? + { + if(!bSkipNextFrame) + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip +#else + eglSwapBuffers(display,surface); +#endif + } + if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } +else // no skip ? + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> swap +#else + eglSwapBuffers(display,surface); +#endif + } + +iDrawnSomething=0; + +//----------------------------------------------------// + +if(lClearOnSwap) // clear buffer after swap? + { + GLclampf g,b,r; + + if(bDisplayNotSet) // -> set new vals + SetOGLDisplaySettings(1); + + g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col + b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; + r=((GLclampf)RED(lClearOnSwapColor))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,128); // -> clear + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + lClearOnSwap=0; // -> done + } +else + { +// if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before + + if(iZBufferDepth) // clear zbuffer as well (if activated) + { + glDisable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); + } + } +gl_z=0.0f; + +//----------------------------------------------------// +// additional uploads immediatly after swapping + +if(bNeedUploadAfter) // upload wanted? + { + bNeedUploadAfter=FALSE; + bNeedUploadTest=FALSE; + UploadScreen(-1); // -> upload + } + +if(bNeedUploadTest) + { + bNeedUploadTest=FALSE; + if(PSXDisplay.InterlacedTest && + //iOffscreenDrawing>2 && + PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + } + } + +//----------------------------------------------------// +// rumbling (main emu pad effect) + +if(iRumbleTime) // shake screen by modifying view port + { + int i1=0,i2=0,i3=0,i4=0; + + iRumbleTime--; + if(iRumbleTime) + { + i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + } + + glViewport(rRatioRect.left+i1, + iResY-(rRatioRect.top+rRatioRect.bottom)+i2, + rRatioRect.right+i3, + rRatioRect.bottom+i4); + } + +//----------------------------------------------------// + + + +// if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled +} + +//////////////////////////////////////////////////////////////////////// +// update front display: smaller update func, if something has changed +// in the frontbuffer... dirty, but hey... real men know no pain +//////////////////////////////////////////////////////////////////////// + +void updateFrontDisplay(void) +{ +if(PreviousPSXDisplay.Range.x0|| + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + +//if(iBlurBuffer) BlurBackBuffer(); + +//if(iUseScanLines) SetScanLines(); + +// if(usCursorActive) ShowGunCursor(); + +bFakeFrontBuffer=FALSE; +bRenderFrontBuffer=FALSE; + +// if(gTexPicName) DisplayPic(); +// if(ulKeybits&KEY_SHOWFPS) DisplayText(); + +#ifdef _WINDOWS + { // windows: + HDC hdc=GetDC(hWWindow); + wglMakeCurrent(hdc,GLCONTEXT); // -> make current again + if(iDrawnSomething) + SwapBuffers(wglGetCurrentDC()); // -> swap + ReleaseDC(hWWindow,hdc); // -> ! important ! + } +#else +if(iDrawnSomething) // linux: + eglSwapBuffers(display,surface); +#endif + +//if(iBlurBuffer) UnBlurBackBuffer(); +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// +void ChangeDispOffsetsX(void) // CENTER X +{ +long lx,l;short sO; + +if(!PSXDisplay.Range.x1) return; // some range given? + +l=PSXDisplay.DisplayMode.x; + +l*=(long)PSXDisplay.Range.x1; // some funky calculation +l/=2560;lx=l;l&=0xfffffff8; + +if(l==PreviousPSXDisplay.Range.x1) return; // some change? + +sO=PreviousPSXDisplay.Range.x0; // store old + +if(lx>=PSXDisplay.DisplayMode.x) // range bigger? + { + PreviousPSXDisplay.Range.x1= // -> take display width + PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 + } +else // range smaller? center it + { + PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) + PreviousPSXDisplay.Range.x0= // -> calc start pos + (PSXDisplay.Range.x0-500)/8; + if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much + PSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= // -> adjust start + PSXDisplay.DisplayMode.x-lx; + PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width + } + } + +if(sO!=PreviousPSXDisplay.Range.x0) // something changed? + { + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // CENTER Y +{ +int iT;short sO; // store previous y size + +if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC + +if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) + { + PreviousPSXDisplay.Range.y1= // -> store width + PSXDisplay.DisplayModeNew.y; + + sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset + if(sO<0) sO=0; + + PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too + } +else sO=0; // else no offset + +if(sO!=PreviousPSXDisplay.Range.y0) // something changed? + { + PreviousPSXDisplay.Range.y0=sO; + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// +// Aspect ratio of ogl screen: simply adjusting ogl view port +//////////////////////////////////////////////////////////////////////// + +void SetAspectRatio(void) +{ +float xs,ys,s;RECT r; + +if(!PSXDisplay.DisplayModeNew.x) return; +if(!PSXDisplay.DisplayModeNew.y) return; + +xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; +ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; + +s=min(xs,ys); +r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); +r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); +if(r.right > iResX) r.right = iResX; +if(r.bottom > iResY) r.bottom = iResY; +if(r.right < 1) r.right = 1; +if(r.bottom < 1) r.bottom = 1; + +r.left = (iResX-r.right)/2; +r.top = (iResY-r.bottom)/2; + +if(r.bottom new psx resolution + PSXDisplay.DisplayModeNew.y, 0, -1, 1); + if(bKeepRatio) SetAspectRatio(); + } + +bDisplayNotSet = TRUE; // re-calc offsets/display area + +bUp=FALSE; +if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) + { + PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet + ResetTextureArea(FALSE); + bUp=TRUE; + } + +PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos +PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; +PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; +PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + +PSXDisplay.DisplayEnd.x= // calc new ends + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; +PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; +PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; +PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + +ChangeDispOffsetsX(); + +if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) + +if(bUp) updateDisplay(); // yeah, real update (swap buffer) +} + +//////////////////////////////////////////////////////////////////////// +// window mode <-> fullscreen mode (windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void ChangeWindowMode(void) +{ + GPUclose(); + bWindowMode=!bWindowMode; + GPUopen(hWWindow); + bChangeWinMode=FALSE; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// swap update check (called by psx vsync function) +//////////////////////////////////////////////////////////////////////// + +BOOL bSwapCheck(void) +{ +static int iPosCheck=0; +static PSXPoint_t pO; +static PSXPoint_t pD; +static int iDoAgain=0; + +if(PSXDisplay.DisplayPosition.x==pO.x && + PSXDisplay.DisplayPosition.y==pO.y && + PSXDisplay.DisplayEnd.x==pD.x && + PSXDisplay.DisplayEnd.y==pD.y) + iPosCheck++; +else iPosCheck=0; + +pO=PSXDisplay.DisplayPosition; +pD=PSXDisplay.DisplayEnd; + +if(iPosCheck<=4) return FALSE; + +iPosCheck=4; + +if(PSXDisplay.Interlaced) return FALSE; + +if (bNeedInterlaceUpdate|| + bNeedRGB24Update || + bNeedUploadAfter|| + bNeedUploadTest || + iDoAgain + ) + { + iDoAgain=0; + if(bNeedUploadAfter) + iDoAgain=1; + if(bNeedUploadTest && PSXDisplay.InterlacedTest) + iDoAgain=1; + + bDisplayNotSet = TRUE; + updateDisplay(); + + PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; + PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + return TRUE; + } + +return FALSE; +} +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// update lace is called every VSync. Basically we limit frame rate +// here, and in interlaced mode we swap ogl display buffers. +//////////////////////////////////////////////////////////////////////// + +static unsigned short usFirstPos=2; + +#ifdef _WINDOWS +void CALLBACK GPUupdateLace(void) +#else +void CALLBACK GPU_updateLace(void) +#endif +{ +if(!(dwActFixes&0x1000)) + STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) + +if(!(dwActFixes&128)) // normal frame limit func + CheckFrameRate(); + +if(iOffscreenDrawing==4) // special check if high offscreen drawing is on + { + if(bSwapCheck()) return; + } + +if(PSXDisplay.Interlaced) // interlaced mode? + { + if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); // -> swap buffers (new frame) + } + } +else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? + { + updateFrontDisplay(); // -> update front buffer + } +else if(usFirstPos==1) // initial updates (after startup) + { + updateDisplay(); + } + +#ifdef _WINDOWS +if(bChangeWinMode) ChangeWindowMode(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadStatus(void) +#else +unsigned long CALLBACK GPU_readStatus(void) +#endif +{ +if(dwActFixes&0x1000) // CC game fix + { + static int iNumRead=0; + if((iNumRead++)==2) + { + iNumRead=0; + STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) + } + } + +if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread... + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + +return STATUSREG; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteStatus(unsigned long gdata) +#else +void CALLBACK GPU_writeStatus(unsigned long gdata) +#endif +{ +unsigned long lCommand=(gdata>>24)&0xff; + +#ifdef _WINDOWS +if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) +#endif + +ulStatusControl[lCommand]=gdata; + +switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long)); + lGPUstatusRet=0x14802000; + PSXDisplay.Disabled=1; + iDataWriteMode=iDataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + + // dis/enable display + case 0x03: + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + STATUSREG|=GPUSTATUS_DISPLAYDISABLED; + else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; + + if (iOffscreenDrawing==4 && + PreviousPSXDisplay.Disabled && + !(PSXDisplay.Disabled)) + { + + if(!PSXDisplay.RGB24) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + updateDisplay(); + } + } + + return; + + // setting transfer mode + case 0x04: + gdata &= 0x03; // only want the lower two bits + + iDataWriteMode=iDataReadMode=DR_NORMAL; + if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; + + STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits + STATUSREG|=(gdata << 29); // set the DMA bits according to the received data + + return; + + // setting display position + case 0x05: + { + short sx=(short)(gdata & 0x3ff); + short sy; + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + sy = (short)((gdata>>12)&0x3ff); + else sy = (short)((gdata>>10)&0x3ff); + } + else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later + + if (sy & 0x200) + { + sy|=0xfc00; + PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; + sy=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + + if(sx>1000) sx=0; + + if(usFirstPos) + { + usFirstPos--; + if(usFirstPos) + { + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + } + + if(dwActFixes&8) + { + if((!PSXDisplay.Interlaced) && + PreviousPSXDisplay.DisplayPosition.x == sx && + PreviousPSXDisplay.DisplayPosition.y == sy) + return; + + PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + } + else + { + if((!PSXDisplay.Interlaced) && + PSXDisplay.DisplayPosition.x == sx && + PSXDisplay.DisplayPosition.y == sy) + return; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + bDisplayNotSet = TRUE; + + if (!(PSXDisplay.Interlaced)) + { + updateDisplay(); + } + else + if(PSXDisplay.InterlacedTest && + ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| + (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) + PSXDisplay.InterlacedTest--; + + return; + } + + // setting width + case 0x06: + + PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; + PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + + // setting height + case 0x07: + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Range.y0=gdata & 0x3ff; + PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if (PreviousPSXDisplay.Height != PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + ChangeDispOffsetsY(); + updateDisplayIfChanged(); + } + return; + + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits + + STATUSREG|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // set the width bits + + PreviousPSXDisplay.InterlacedNew=FALSE; + if (PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PSXDisplay.InterlacedTest=2; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.InterlacedNew=TRUE; + } + + STATUSREG|=GPUSTATUS_INTERLACED; + } + else + { + PSXDisplay.InterlacedTest=0; + STATUSREG&=~GPUSTATUS_INTERLACED; + } + + if (PSXDisplay.PAL) + STATUSREG|=GPUSTATUS_PAL; + else STATUSREG&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; + else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + STATUSREG|=GPUSTATUS_RGB24; + else STATUSREG&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + GPUdataRet=0x01; + else GPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + GPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers +//////////////////////////////////////////////////////////////////////// + +BOOL bNeedWriteUpload=FALSE; + +__inline void FinishedVRAMWrite(void) +{ + if(bNeedWriteUpload) + { + bNeedWriteUpload=FALSE; + CheckWriteUpdate(); + } + + // set register to NORMAL operation + iDataWriteMode = DR_NORMAL; + + // reset transfer values, to prevent mis-transfer of data + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +__inline void FinishedVRAMRead(void) +{ + // set register to NORMAL operation + iDataReadMode = DR_NORMAL; + // reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + STATUSREG&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// vram read check ex (reading from card's back/frontbuffer if needed... +// slow!) +//////////////////////////////////////////////////////////////////////// + +void CheckVRamReadEx(int x, int y, int dx, int dy) +{ + unsigned short sArea; + int ux,uy,udx,udy,wx,wy; + unsigned short * p1, *p2; + float XS,YS; + u8 * ps; + u8 * px; + unsigned short s,sx; + + if(STATUSREG&GPUSTATUS_RGB24) return; + + if(((dx > PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + ////////////// + + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + + ////////////// + + p2=0; + + if(sArea==0) + { + ux=PSXDisplay.DisplayPosition.x; + uy=PSXDisplay.DisplayPosition.y; + udx=PSXDisplay.DisplayEnd.x-ux; + udy=PSXDisplay.DisplayEnd.y-uy; + if((PreviousPSXDisplay.DisplayEnd.x- + PreviousPSXDisplay.DisplayPosition.x)==udx && + (PreviousPSXDisplay.DisplayEnd.y- + PreviousPSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + + PreviousPSXDisplay.DisplayPosition.x); + } + else + { + ux=PreviousPSXDisplay.DisplayPosition.x; + uy=PreviousPSXDisplay.DisplayPosition.y; + udx=PreviousPSXDisplay.DisplayEnd.x-ux; + udy=PreviousPSXDisplay.DisplayEnd.y-uy; + if((PSXDisplay.DisplayEnd.x- + PSXDisplay.DisplayPosition.x)==udx && + (PSXDisplay.DisplayEnd.y- + PSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + + PSXDisplay.DisplayPosition.x); + } + + p1=(psxVuw + (1024*uy) + ux); + if(p1==p2) p2=0; + + x=0;y=0; + wx=dx=udx;wy=dy=udy; + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + //if(!sArea) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + //if(!sArea) glReadBuffer(GL_BACK); + + s=0; + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p1>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p1=s; + } + if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + if(dwActFixes&0x40) + { + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + } + + ux=x;uy=y;udx=dx;udy=dy; + + if(sArea==0) + { + x -=PSXDisplay.DisplayPosition.x; + dx-=PSXDisplay.DisplayPosition.x; + y -=PSXDisplay.DisplayPosition.y; + dy-=PSXDisplay.DisplayPosition.y; + wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; + wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; + } + else + { + x -=PreviousPSXDisplay.DisplayPosition.x; + dx-=PreviousPSXDisplay.DisplayPosition.x; + y -=PreviousPSXDisplay.DisplayPosition.y; + dy-=PreviousPSXDisplay.DisplayPosition.y; + wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; + wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; + } + if(x<0) {ux-=x;x=0;} + if(y<0) {uy-=y;y=0;} + if(dx>wx) {udx-=(dx-wx);dx=wx;} + if(dy>wy) {udy-=(dy-wy);dy=wy;} + udx-=ux; + udy-=uy; + + p=(psxVuw + (1024*uy) + ux); + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + x=(int)((float)x*XS); + y=(int)((float)y*YS); + + dx-=x; + dy-=y; + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + +// if(bFront) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + +// if(bFront) glReadBuffer(GL_BACK); + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p=s; + } + p++; + } + p += 1024 - udx; + } +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize) +#else +void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize) +#endif +{ +int i; + +if(iDataReadMode!=DR_VRAMTRANSFER) return; + +GPUIsBusy; + +// adjust read ptr, if necessary +while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; +while(VRAMRead.ImagePtr1) && + !(iDrawnSomething==2 && + VRAMRead.x == VRAMWrite.x && + VRAMRead.y == VRAMWrite.y && + VRAMRead.Width == VRAMWrite.Width && + VRAMRead.Height == VRAMWrite.Height)) + CheckVRamRead(VRAMRead.x,VRAMRead.y, + VRAMRead.x+VRAMRead.RowsRemaining, + VRAMRead.y+VRAMRead.ColsRemaining, + TRUE); + +for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + GPUdataRet=(unsigned long)*VRAMRead.ImagePtr; + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16; + *pMem++=GPUdataRet; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: +GPUIsIdle; +} + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadData(void) +#else +unsigned long CALLBACK GPU_readData(void) +#endif +{ + unsigned long l; +#ifdef _WINDOWS + GPUreadDataMem(&l,1); +#else + GPU_readDataMem(&l,1); +#endif + return GPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// helper table to know how much data is used by drawing commands +//////////////////////////////////////////////////////////////////////// + +const u8 primTableCX[256] = +{ + // 00 + 0,0,3,0,0,0,0,0, + // 08 + 0,0,0,0,0,0,0,0, + // 10 + 0,0,0,0,0,0,0,0, + // 18 + 0,0,0,0,0,0,0,0, + // 20 + 4,4,4,4,7,7,7,7, + // 28 + 5,5,5,5,9,9,9,9, + // 30 + 6,6,6,6,9,9,9,9, + // 38 + 8,8,8,8,12,12,12,12, + // 40 + 3,3,3,3,0,0,0,0, + // 48 +// 5,5,5,5,6,6,6,6, //FLINE + 254,254,254,254,254,254,254,254, + // 50 + 4,4,4,4,0,0,0,0, + // 58 +// 7,7,7,7,9,9,9,9, // LINEG3 LINEG4 + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, // TILE SPRT + // 68 + 2,2,2,2,3,3,3,3, // TILE1 + // 70 + 2,2,2,2,3,3,3,3, + // 78 + 2,2,2,2,3,3,3,3, + // 80 + 4,0,0,0,0,0,0,0, + // 88 + 0,0,0,0,0,0,0,0, + // 90 + 0,0,0,0,0,0,0,0, + // 98 + 0,0,0,0,0,0,0,0, + // a0 + 3,0,0,0,0,0,0,0, + // a8 + 0,0,0,0,0,0,0,0, + // b0 + 0,0,0,0,0,0,0,0, + // b8 + 0,0,0,0,0,0,0,0, + // c0 + 3,0,0,0,0,0,0,0, + // c8 + 0,0,0,0,0,0,0,0, + // d0 + 0,0,0,0,0,0,0,0, + // d8 + 0,0,0,0,0,0,0,0, + // e0 + 0,1,1,1,1,1,1,0, + // e8 + 0,0,0,0,0,0,0,0, + // f0 + 0,0,0,0,0,0,0,0, + // f8 + 0,0,0,0,0,0,0,0 +}; + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize) +#else +void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize) +#endif +{ +u8 command; +unsigned long gdata=0; +int i=0; +GPUIsBusy; +GPUIsNotReadyForCommands; + +STARTVRAM: + +if(iDataWriteMode==DR_VRAMTRANSFER) + { + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=*pMem++; + + *VRAMWrite.ImagePtr++ = (unsigned short)gdata; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + FinishedVRAMWrite(); + } + +ENDVRAM: + +if(iDataWriteMode==DR_NORMAL) + { + void (* *primFunc)(u8 *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i>24) & 0xff); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + gpuDataM[0] = gdata; + gpuDataP = 1; + } + else continue; + } + else + { + gpuDataM[gpuDataP] = gdata; + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((u8 *)gpuDataM); + + if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + +GPUdataRet=gdata; + +GPUIsReadyForCommands; +GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteData(unsigned long gdata) +#else +void CALLBACK GPU_writeData(unsigned long gdata) +#endif +{ +#ifdef _WINDOWS + GPUwriteDataMem(&gdata,1); +#else + GPU_writeDataMem(&gdata,1); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// this function will be removed soon (or 'soonish') (or never) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned int gdata) +{ + // ignore old psemu setmode: + + // imageTransfer = gdata; + // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; + // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +// and this function will be removed soon as well, hehehe... +long CALLBACK GPUgetMode(void) +{ + // ignore old psemu setmode + // return imageTransfer; + +long iT=0; + +if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1; +if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + +return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg (Windows + Linux) +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS + +/*#include + +void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool +{ + FILE * cf;s8 filename[255],t[255]; + + strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir("cfg"); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else + { + strcpy(filename,"cfgPeopsMesaGL"); // look in current folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + } + else + { + sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir(getenv("HOME")); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else printf("cfgPeopsMesaGL not found!\n"); + } + } +} +*/ +#endif + + +#ifdef _WINDOWS +long CALLBACK GPUconfigure(void) +#else +long CALLBACK GPU_configure(void) +#endif +{ + +#ifdef _WINDOWS +// HWND hWP=GetActiveWindow(); +// DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), +// hWP,(DLGPROC)CfgDlgProc); +#else + +// StartCfgTool("CFG"); + +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) +{ + ReInitFrameCap(); + + if(dwActFixes & 0x2000) + dispWidths[4]=384; + else dispWidths[4]=368; +} + +//////////////////////////////////////////////////////////////////////// +// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(unsigned long laddr) +{ +if(laddr==lUsedAddr[1]) return TRUE; +if(laddr==lUsedAddr[2]) return TRUE; + +if(laddr 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + +#ifdef _WINDOWS + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); +#else + if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count); +#endif + + addr = baseAddrL[addr>>2]&0xffffff; + } +while (addr != 0xffffff); + +GPUIsIdle; + +return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUabout(void) +#else +void CALLBACK GPU_about(void) +#endif +{ + +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUtest(void) +#else +long CALLBACK GPU_test(void) +#endif +{ + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// save state funcs +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#else +long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#endif +{ +if(ulGetFreezeData==2) + { + long lSlotNum=*((long *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + return 1; + } + +if(!pF) return 0; +if(pF->ulFreezeVersion!=1) return 0; + +if(ulGetFreezeData==1) + { + pF->ulStatus=STATUSREG; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + +if(ulGetFreezeData!=0) return 0; + +STATUSREG=pF->ulStatus; +memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long)); +memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +ResetTextureArea(TRUE); + +#ifdef _WINDOWS + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); +#else + GPU_writeStatus(ulStatusControl[0]); + GPU_writeStatus(ulStatusControl[1]); + GPU_writeStatus(ulStatusControl[2]); + GPU_writeStatus(ulStatusControl[3]); + GPU_writeStatus(ulStatusControl[8]); + GPU_writeStatus(ulStatusControl[6]); + GPU_writeStatus(ulStatusControl[7]); + GPU_writeStatus(ulStatusControl[5]); + GPU_writeStatus(ulStatusControl[4]); +#endif + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// special "emu infos" / "emu effects" functions +//////////////////////////////////////////////////////////////////////// + +//00 = black +//01 = white +//10 = red +//11 = transparent + +u8 cFont[10][120]= +{ +// 0 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 1 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 2 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 3 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 4 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x14,0x00,0x00, + 0x80,0x00,0x14,0x14,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 5 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 6 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x15,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 7 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 8 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 9 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x15,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +} +}; + +//////////////////////////////////////////////////////////////////////// + +void PaintPicDot(u8 * p,u8 c) +{ + if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUgetScreenPic(u8 * pMem) +#else +long CALLBACK GPU_getScreenPic(u8 * pMem) +#endif +{ + float XS,YS;int x,y,v; + u8 * ps, * px, * pf; + u8 c; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + +// glReadBuffer(GL_FRONT); + + glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); + +// glReadBuffer(GL_BACK); + + XS=(float)iResX/128; + YS=(float)iResY/96; + pf=pMem; + + for(y=96;y>0;y--) + { + for(x=0;x<128;x++) + { + px=ps+(3*((int)((float)x * XS))+ + (3*iResX)*((int)((float)y*YS))); + *(pf+0)=*(px+2); + *(pf+1)=*(px+1); + *(pf+2)=*(px+0); + pf+=3; + } + } + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); + + for(y=0;y<20;y++) + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; + v=(c&0xc0)>>6; + PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(u8)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(u8)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(u8)v);pf+=3; + } + pf+=104*3; + } + + pf=pMem; + for(x=0;x<128;x++) + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; + for(y=0;y<96;y++) + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; + } + +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUshowScreenPic(u8 * pMem) +#else +long CALLBACK GPU_showScreenPic(u8 * pMem) +#endif +{ +// DestroyPic(); +// if(pMem==0) return; +// CreatePic(pMem); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetfix(unsigned long dwFixBits) +{ + dwEmuFixes=dwFixBits; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig) +{ + int iVibVal; + + if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); + else iVibVal=1; + // big rumble: 4...15 sp ; small rumble 1...3 sp + if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); + else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); + + srand(timeGetTime()); // init rand (will be used in BufferSwap) + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} + +//////////////////////////////////////////////////////////////////////// +// main emu can set display infos (A/M/G/D) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUdisplayFlags(unsigned long dwFlags) +{ +// dwCoreFlags=dwFlags; +} diff --git a/plugins/gpu-gles/gpuPlugin.h b/plugins/gpu-gles/gpuPlugin.h new file mode 100644 index 00000000..c4520322 --- /dev/null +++ b/plugins/gpu-gles/gpuPlugin.h @@ -0,0 +1,134 @@ +/*************************************************************************** + gpu.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _GPU_PLUGIN_H +#define _GPU_PLUGIN_H + +///////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_WINDOWS) && !defined(__NANOGL__) +#define glOrtho(x,y,z,xx,yy,zz) glOrthof(x,y,z,xx,yy,zz) +#endif + +#define PRED(x) ((x << 3) & 0xF8) +#define PBLUE(x) ((x >> 2) & 0xF8) +#define PGREEN(x) ((x >> 7) & 0xF8) + +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + +#ifdef _WINDOWS +#include "Externals.h" +#include "plugin.h" +#include +#else +#ifndef MAEMO_CHANGES + #include "psxCommon.h" +#else + #include "../psxCommon.h" +#endif +#include "gpuExternals.h" +#ifdef __NANOGL__ +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifndef MAEMO_CHANGES + #include // for opengl es types + #include +#else +#include "gpuStdafx.h" +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#endif +///////////////////////////////////////////////////////////////////////////// + +#define CALLBACK + +#define bool unsigned short + +typedef struct { + u32 ulFreezeVersion; + u32 ulStatus; + u32 ulControl[256]; + u8 psxVRam[1024*1024*2]; +} GPUFreeze_t; + +long CALLBACK GPU_init(); +long CALLBACK GPU_shutdown(); +long CALLBACK GPU_open(int hwndGPU); +long CALLBACK GPU_close(); +unsigned long CALLBACK GPU_readData(void); +void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize); +unsigned long CALLBACK GPU_readStatus(void); +void CALLBACK GPU_writeData(unsigned long gdata); +void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize); +void CALLBACK GPU_writeStatus(unsigned long gdata); +long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr); +void CALLBACK GPU_updateLace(void); +void CALLBACK GPU_makeSnapshot(void); +long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF); +long CALLBACK GPU_getScreenPic(u8 * pMem); +long CALLBACK GPU_showScreenPic(u8 * pMem); +//void CALLBACK GPU_keypressed(int keycode); +//void CALLBACK GPU_displayText(s8 * pText); +//void CALLBACK GPU_clearDynarec(void (CALLBACK *callback)(void)); +long CALLBACK GPU_configure(void); +long CALLBACK GPU_test(void); +void CALLBACK GPU_about(void); + + +void DoSnapShot(void); +void GPU_vSinc(void); +void updateDisplay(void); +void updateFrontDisplay(void); +void SetAutoFrameCap(void); +void SetAspectRatio(void); +void CheckVRamRead(int x, int y, int dx, int dy, bool bFront); +void CheckVRamReadEx(int x, int y, int dx, int dy); +void SetFixes(void); + +void PaintPicDot(u8 * p,u8 c); +//void DrawNumBorPic(u8 *pMem, int lSelectedSlot); +void ResizeWindow(); + +//////////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +} +#endif + + +#endif // _GPU_INTERNALS_H diff --git a/plugins/gpu-gles/gpuPrim.c b/plugins/gpu-gles/gpuPrim.c new file mode 100644 index 00000000..9b718a5f --- /dev/null +++ b/plugins/gpu-gles/gpuPrim.c @@ -0,0 +1,5022 @@ +/*************************************************************************** + prim.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define _IN_PRIMDRAW + +#ifdef _WINDOWS +#include "stdafx.h" +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "texture.h" +#else +#include "gpuStdafx.h" +#include "gpuExternals.h" +#include "gpuPlugin.h" +#include "gpuDraw.h" +#include "gpuTexture.h" +#include "gpuPrim.h" + +#endif + +//////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////// + +#define DEFOPAQUEON glAlphaFunc(GL_EQUAL,0.0f);bBlendEnable=FALSE;glDisable(GL_BLEND); +#define DEFOPAQUEOFF glAlphaFunc(GL_GREATER,0.49f); +#define fpoint(x) x +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS +EGLSurface surface; +EGLDisplay display; +#endif + +BOOL bDrawTextured; // current active drawing states +BOOL bDrawSmoothShaded; +BOOL bOldSmoothShaded; +BOOL bDrawNonShaded; +BOOL bDrawMultiPass; +int iOffscreenDrawing; +int iDrawnSomething=0; + +BOOL bRenderFrontBuffer=FALSE; // flag for front buffer rendering + +GLubyte ubGloAlpha; // texture alpha +GLubyte ubGloColAlpha; // color alpha +int iFilterType; // type of filter +BOOL bFullVRam=FALSE; // sign for tex win +BOOL bDrawDither; // sign for dither +BOOL bUseMultiPass; // sign for multi pass +GLuint gTexName; // binded texture +BOOL bTexEnabled; // texture enable flag +BOOL bBlendEnable; // blend enable flag +PSXRect_t xrUploadArea; // rect to upload +PSXRect_t xrUploadAreaIL; // rect to upload +PSXRect_t xrUploadAreaRGB24; // rect to upload rgb24 +int iSpriteTex=0; // flag for "hey, it's a sprite" +unsigned short usMirror; // mirror, mirror on the wall + +BOOL bNeedUploadAfter=FALSE; // sign for uploading in next frame +BOOL bNeedUploadTest=FALSE; // sign for upload test +BOOL bUsingTWin=FALSE; // tex win active flag +BOOL bUsingMovie=FALSE; // movie active flag +PSXRect_t xrMovieArea; // rect for movie upload +short sSprite_ux2; // needed for sprire adjust +short sSprite_vy2; // +unsigned long ulOLDCOL=0; // active color +unsigned long ulClutID; // clut + +unsigned long dwCfgFixes; // game fixes +unsigned long dwActFixes=0; +unsigned long dwEmuFixes=0; +BOOL bUseFixes; + +long drawX,drawY,drawW,drawH; // offscreen drawing checkers +short sxmin,sxmax,symin,symax; + +//////////////////////////////////////////////////////////////////////// +// Update global TP infos +//////////////////////////////////////////////////////////////////////// + +void UpdateGlobalTP(unsigned short gdata) +{ + GlobalTextAddrX = (gdata << 6) & 0x3c0; + + if(iGPUHeight==1024) // ZN mode + { + if(dwGPUVersion==2) // very special zn gpu + { + GlobalTextAddrY =((gdata & 0x60 ) << 3); + GlobalTextIL =(gdata & 0x2000) >> 13; + GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); + GlobalTextTP = (gdata >> 9) & 0x3; + if(GlobalTextTP==3) GlobalTextTP=2; + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + usMirror =0; + STATUSREG = (STATUSREG & 0xffffe000 ) | (gdata & 0x1fff ); + return; + } + else // "enhanced" psx gpu + { + GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); + } + } + else GlobalTextAddrY = (gdata << 4) & 0x100; // "normal" psx gpu + + usMirror=gdata&0x3000; + + GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( + GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + + STATUSREG&=~0x07ff; // Clear the necessary bits + STATUSREG|=(gdata & 0x07ff); // set the necessary bits +} + +//////////////////////////////////////////////////////////////////////// +// Some ASM color convertion... Lewpy's special... +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +#pragma warning (disable : 4035) + +unsigned long DoubleBGR2RGB (unsigned long BGR) +{ + + __asm + { + mov eax, BGR /* this can hold the G value */ + mov ebx, eax /* this can hold the R value */ + mov edx, eax /* this can hold the B value */ + and ebx, 000000ffh /* mask the R value */ + shl ebx, 1 + test ebx, 00000100h + jz RSKIP + mov ebx, 000000ffh + +RSKIP: + and eax, 0000ff00h /* mask the G value */ + shl eax, 1 + test eax, 00010000h + jz GSKIP + mov eax, 0000ff00h + +GSKIP: + and edx, 00ff0000h /* mask the B value */ + shl edx, 1 + test edx, 01000000h + jz BSKIP + mov edx, 00ff0000h + +BSKIP: + or eax, ebx /* add R to G value */ + or eax, edx /* add B to RG value */ + } + /* Result returned in EAX */ +} + +unsigned short BGR24to16 (unsigned long BGR) +{ + __asm + { + mov eax, BGR /* this can hold the G value */ + mov ebx, eax /* this can hold the R value */ + mov edx, eax /* this can hold the B value */ + shr ebx, 3 /* move the R value */ + and edx, 00f80000h /* mask the B value */ + shr edx, 9 /* move the B value */ + and eax, 00f800h /* mask the G value */ + shr eax, 6 /* move the G value */ + and ebx, 0000001fh /* mask the R value */ + or eax, ebx /* add R to G value */ + or eax, edx /* add B to RG value */ + } + /* Result returned in AX */ +} + +#pragma warning (default : 4035) + +#else + +unsigned long DoubleBGR2RGB (unsigned long BGR) +{ + unsigned long ebx,eax,edx; + + ebx=(BGR&0x000000ff)<<1; + if(ebx&0x00000100) ebx=0x000000ff; + + eax=(BGR&0x0000ff00)<<1; + if(eax&0x00010000) eax=0x0000ff00; + + edx=(BGR&0x00ff0000)<<1; + if(edx&0x01000000) edx=0x00ff0000; + + return (ebx|eax|edx); +} + +unsigned short BGR24to16 (unsigned long BGR) +{ + return ((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// OpenGL primitive drawing commands +//////////////////////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + + +Vertex v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].st.x = fpoint(vertex4->sow); +v[2].st.y = fpoint(vertex4->tow); + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].st.x = fpoint(vertex3->sow); +v[3].st.y = fpoint(vertex3->tow); + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedTri(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ +Vertex v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].st.x = fpoint(vertex3->sow); +v[2].st.y = fpoint(vertex3->tow); + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); + +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ + +Vertex2 v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].st.x = fpoint(vertex3->sow); +v[2].st.y = fpoint(vertex3->tow); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColorQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].st.x = fpoint(vertex4->sow); +v[2].st.y = fpoint(vertex4->tow); +v[2].rgba.r = vertex4->c.col[0]; +v[2].rgba.g = vertex4->c.col[1]; +v[2].rgba.b = vertex4->c.col[2]; +v[2].rgba.a = vertex4->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].st.x = fpoint(vertex3->sow); +v[3].st.y = fpoint(vertex3->tow); +v[3].rgba.r = vertex3->c.col[0]; +v[3].rgba.g = vertex3->c.col[1]; +v[3].rgba.b = vertex3->c.col[2]; +v[3].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3) +{ +Vec3f v[3]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex2->x); +v[1].y = fpoint(vertex2->y); +v[1].z = fpoint(vertex2->z); + +v[2].x = fpoint(vertex3->x); +v[2].y = fpoint(vertex3->y); +v[2].z = fpoint(vertex3->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri2(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vec3f v[4]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex3->x); +v[1].y = fpoint(vertex3->y); +v[1].z = fpoint(vertex3->z); + +v[2].x = fpoint(vertex2->x); +v[2].y = fpoint(vertex2->y); +v[2].z = fpoint(vertex2->z); + +v[3].x = fpoint(vertex4->x); +v[3].y = fpoint(vertex4->y); +v[3].z = fpoint(vertex4->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ +Vertex2 v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTri2Color(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +v[3].xyz.x = fpoint(vertex4->x); +v[3].xyz.y = fpoint(vertex4->y); +v[3].xyz.z = fpoint(vertex4->z); +v[3].rgba.r = vertex4->c.col[0]; +v[3].rgba.g = vertex4->c.col[1]; +v[3].rgba.b = vertex4->c.col[2]; +v[3].rgba.a = vertex4->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawFlatLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex1->c.col[0]; +v[1].rgba.g = vertex1->c.col[1]; +v[1].rgba.b = vertex1->c.col[2]; +v[1].rgba.a = vertex1->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].rgba.r = vertex1->c.col[0]; +v[2].rgba.g = vertex1->c.col[1]; +v[2].rgba.b = vertex1->c.col[2]; +v[2].rgba.a = vertex1->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].rgba.r = vertex1->c.col[0]; +v[3].rgba.g = vertex1->c.col[1]; +v[3].rgba.b = vertex1->c.col[2]; +v[3].rgba.a = vertex1->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); + + +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ + Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].rgba.r = vertex3->c.col[0]; +v[3].rgba.g = vertex3->c.col[1]; +v[3].rgba.b = vertex3->c.col[2]; +v[3].rgba.a = vertex3->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].rgba.r = vertex4->c.col[0]; +v[2].rgba.g = vertex4->c.col[1]; +v[2].rgba.b = vertex4->c.col[2]; +v[2].rgba.a = vertex4->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vec3f v[4]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex2->x); +v[1].y = fpoint(vertex2->y); +v[1].z = fpoint(vertex2->z); + +v[2].x = fpoint(vertex4->x); +v[2].y = fpoint(vertex4->y); +v[2].z = fpoint(vertex4->z); + +v[3].x = fpoint(vertex3->x); +v[3].y = fpoint(vertex3->y); +v[3].z = fpoint(vertex3->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +} + +//////////////////////////////////////////////////////////////////////// +// Transparent blending settings +//////////////////////////////////////////////////////////////////////// + +static GLenum obm1=GL_ZERO; +static GLenum obm2=GL_ZERO; + +typedef struct SEMITRANSTAG +{ + GLenum srcFac; + GLenum dstFac; + GLubyte alpha; +} SemiTransParams; + +SemiTransParams TransSets[4]= +{ + {GL_SRC_ALPHA,GL_SRC_ALPHA, 127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 192} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTrans(void) +{ +/* +* 0.5 x B + 0.5 x F +* 1.0 x B + 1.0 x F +* 1.0 x B - 1.0 x F +* 1.0 x B +0.25 x F +*/ + + if(!DrawSemiTrans) // no semi trans at all? + { + if(bBlendEnable) + {glDisable(GL_BLEND);bBlendEnable=FALSE;} // -> don't wanna blend + ubGloAlpha=ubGloColAlpha=255; // -> full alpha + return; // -> and bye + } + + ubGloAlpha=ubGloColAlpha=TransSets[GlobalTextABR].alpha; + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(TransSets[GlobalTextABR].srcFac!=obm1 || + TransSets[GlobalTextABR].dstFac!=obm2) + { + //if(glBlendEquationEXTEx==NULL) + { + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + /*else + if(TransSets[GlobalTextABR].dstFac !=GL_ONE_MINUS_SRC_COLOR) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + else + { + glBlendEquationEXTEx(FUNC_REVERSESUBTRACT_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(GL_ONE,GL_ONE); // set blend func + }*/ + } +} + +void SetScanTrans(void) // blending for scan lines +{ +/* if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } +*/ + obm1=TransSets[0].srcFac; + obm2=TransSets[0].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +void SetScanTexTrans(void) // blending for scan mask texture +{ +/* if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } +*/ + obm1=TransSets[2].srcFac; + obm2=TransSets[2].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +//////////////////////////////////////////////////////////////////////// +// multi pass in old 'Advanced blending' mode... got it from Lewpy :) +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiTexTransSets[4][2]= +{ + { + {GL_ONE ,GL_SRC_ALPHA, 127}, + {GL_SRC_ALPHA,GL_ONE, 127} + }, + { + {GL_ONE, GL_SRC_ALPHA, 255}, + {GL_SRC_ALPHA,GL_ONE, 255} + }, + { + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255} + }, + { + {GL_SRC_ALPHA,GL_ONE, 127}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 255} + } +}; + +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiColTransSets[4]= +{ + {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA,127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_SRC_ALPHA,GL_ONE, 127} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTransMulti(int Pass) +{ + static GLenum bm1=GL_ZERO; + static GLenum bm2=GL_ONE; + + ubGloAlpha=255; + ubGloColAlpha=255; + + // are we enabling SemiTransparent mode? + if(DrawSemiTrans) + { + if(bDrawTextured) + { + bm1=MultiTexTransSets[GlobalTextABR][Pass].srcFac; + bm2=MultiTexTransSets[GlobalTextABR][Pass].dstFac; + ubGloAlpha=MultiTexTransSets[GlobalTextABR][Pass].alpha; + } + // no texture + else + { + bm1=MultiColTransSets[GlobalTextABR].srcFac; + bm2=MultiColTransSets[GlobalTextABR].dstFac; + ubGloColAlpha=MultiColTransSets[GlobalTextABR].alpha; + } + } + // no shading + else + { + if(Pass==0) + { + // disable blending + bm1=GL_ONE;bm2=GL_ZERO; + } + else + { + // disable blending, but add src col a second time + bm1=GL_ONE;bm2=GL_ONE; + } + } + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(bm1!=obm1 || bm2!=obm2) + { + glBlendFunc(bm1,bm2); // set blend func + obm1=bm1;obm2=bm2; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set several rendering stuff including blending +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask3O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask3(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask3NT(void) +{ + if(iUseMask) + { + if(iSetMask) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask4O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask4(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4NT(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4SP(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + if(bCheckMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + else + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderState(unsigned long DrawAttributes) +{ + bDrawNonShaded = (SHADETEXBIT(DrawAttributes)) ? TRUE : FALSE; + DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderColor(unsigned long DrawAttributes) +{ + if(bDrawNonShaded) {g_m1=g_m2=g_m3=128;} + else + { + g_m1=DrawAttributes&0xff; + g_m2=(DrawAttributes>>8)&0xff; + g_m3=(DrawAttributes>>16)&0xff; + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetRenderMode(unsigned long DrawAttributes,BOOL bSCol) +{ + if((bUseMultiPass) && (bDrawTextured) && !(bDrawNonShaded)) + {bDrawMultiPass = TRUE; SetSemiTransMulti(0);} + else {bDrawMultiPass = FALSE;SetSemiTrans();} + + if(bDrawTextured) // texture ? build it/get it from cache + { + GLuint currTex; + if(bUsingTWin) currTex=LoadTextureWnd(GlobalTexturePage,GlobalTextTP, ulClutID); + else if(bUsingMovie) currTex=LoadTextureMovie(); + else currTex=SelectSubTextureS(GlobalTextTP,ulClutID); + + if(gTexName!=currTex) + {gTexName=currTex;glBindTexture(GL_TEXTURE_2D,currTex);} + + if(!bTexEnabled) // -> turn texturing on + {bTexEnabled=TRUE;glEnable(GL_TEXTURE_2D);} + } + else // no texture ? + if(bTexEnabled) + {bTexEnabled=FALSE;glDisable(GL_TEXTURE_2D);} // -> turn texturing off + + if(bSCol) // also set color ? + { + if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) + DrawAttributes|=0x007f7f7f; + + if(bDrawNonShaded) // -> non shaded? + { +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; // --> solid color... + else */vertex[0].c.lcol=0xffffff; + } + else // -> shaded? + { +// if(!bUseMultiPass && !bGLBlend) // --> given color... + vertex[0].c.lcol=DoubleBGR2RGB(DrawAttributes); +// else vertex[0].c.lcol=DrawAttributes; + } + vertex[0].c.col[3]=ubGloAlpha; // -> set color with + SETCOL(vertex[0]); // texture alpha + } + + if(bDrawSmoothShaded!=bOldSmoothShaded) // shading changed? + { + if(bDrawSmoothShaded) glShadeModel(GL_SMOOTH); // -> set actual shading + else glShadeModel(GL_FLAT); + bOldSmoothShaded=bDrawSmoothShaded; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set Opaque multipass color +//////////////////////////////////////////////////////////////////////// + +void SetOpaqueColor(unsigned long DrawAttributes) +{ + if(bDrawNonShaded) return; // no shading? bye + + DrawAttributes=DoubleBGR2RGB(DrawAttributes); // multipass is just half color, so double it on opaque pass + vertex[0].c.lcol=DrawAttributes|0xff000000; + SETCOL(vertex[0]); // set color +} + +//////////////////////////////////////////////////////////////////////// +// Fucking stupid screen coord checking +//////////////////////////////////////////////////////////////////////// + +BOOL ClipVertexListScreen(void) +{ + if (lx0 >= PSXDisplay.DisplayEnd.x) goto NEXTSCRTEST; + if (ly0 >= PSXDisplay.DisplayEnd.y) goto NEXTSCRTEST; + if (lx2 < PSXDisplay.DisplayPosition.x) goto NEXTSCRTEST; + if (ly2 < PSXDisplay.DisplayPosition.y) goto NEXTSCRTEST; + + return TRUE; + +NEXTSCRTEST: + if(PSXDisplay.InterlacedTest) return FALSE; + + if (lx0 >= PreviousPSXDisplay.DisplayEnd.x) return FALSE; + if (ly0 >= PreviousPSXDisplay.DisplayEnd.y) return FALSE; + if (lx2 < PreviousPSXDisplay.DisplayPosition.x) return FALSE; + if (ly2 < PreviousPSXDisplay.DisplayPosition.y) return FALSE; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreenFront(void) +{ + if(sxmin < PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(symin < PSXDisplay.DisplayPosition.y) return FALSE; + if(sxmax > PSXDisplay.DisplayEnd.x) return FALSE; + if(symax > PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bOnePointInFront(void) +{ + if(sxmax< PSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + + +BOOL bOnePointInBack(void) +{ + if(sxmax< PreviousPSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PreviousPSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PreviousPSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PreviousPSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + +BOOL bDrawOffscreen4(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,max(lx2,lx3))); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,max(ly2,ly3))); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + if(dwActFixes&1 && iOffscreenDrawing==4) + { + if(PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + bRenderFrontBuffer=TRUE; + return FALSE; + } + } + + sW=drawW-1;sH=drawH-1; + + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4 && !(dwActFixes&1)) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + //return TRUE; + } + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreen3(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,lx2)); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,ly2)); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + sW=drawW-1;sH=drawH-1; + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + // return TRUE; + } + + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareFullScreenUpload (long Position) +{ + if (Position==-1) // rgb24 + { + if(PSXDisplay.Interlaced) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if(bNeedRGB24Update) + { + if(lClearOnSwap) + { +// lClearOnSwap=0; + } + else + if(PSXDisplay.Interlaced && PreviousPSXDisplay.RGB24<2) // in interlaced mode we upload at least two full frames (GT1 menu) + { + PreviousPSXDisplay.RGB24++; + } + else + { + xrUploadArea.y1 = min(xrUploadArea.y0+xrUploadAreaRGB24.y1,xrUploadArea.y1); + xrUploadArea.y0+=xrUploadAreaRGB24.y0; + } + } + } + else + if (Position) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if (xrUploadArea.x0 < 0) xrUploadArea.x0 = 0; + else + if (xrUploadArea.x0 > 1023) xrUploadArea.x0 = 1023; + + if (xrUploadArea.x1 < 0) xrUploadArea.x1 = 0; + else + if (xrUploadArea.x1 > 1024) xrUploadArea.x1 = 1024; + + if (xrUploadArea.y0 < 0) xrUploadArea.y0 = 0; + else + if (xrUploadArea.y0 > iGPUHeightMask) xrUploadArea.y0 = iGPUHeightMask; + + if (xrUploadArea.y1 < 0) xrUploadArea.y1 = 0; + else + if (xrUploadArea.y1 > iGPUHeight) xrUploadArea.y1 = iGPUHeight; + + if (PSXDisplay.RGB24) + { + InvalidateTextureArea(xrUploadArea.x0,xrUploadArea.y0,xrUploadArea.x1-xrUploadArea.x0,xrUploadArea.y1-xrUploadArea.y0); + } +} + +//////////////////////////////////////////////////////////////////////// +// Upload screen (MDEC and such) +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +u8 * LoadDirectMovieFast(void); + +void UploadScreenEx(long Position) +{ + short ya,yb,xa,xb,x, y, YStep, XStep, U, UStep,ux[4],vy[4]; + + if(!PSXDisplay.DisplayMode.x) return; + if(!PSXDisplay.DisplayMode.y) return; + + glDisable(GL_SCISSOR_TEST); + glShadeModel(GL_FLAT); + bOldSmoothShaded=FALSE; + glDisable(GL_BLEND); + bBlendEnable=FALSE; + glDisable(GL_TEXTURE_2D); + bTexEnabled=FALSE; + glDisable(GL_ALPHA_TEST); + + //glPixelZoom(((float)rRatioRect.right)/((float)PSXDisplay.DisplayMode.x), + // -1.0f*(((float)rRatioRect.bottom)/((float)PSXDisplay.DisplayMode.y))); + + //----------------------------------------------------// + + YStep = 256; // max texture size + XStep = 256; + UStep = (PSXDisplay.RGB24 ? 128 : 0); + ya = xrUploadArea.y0; + yb = xrUploadArea.y1; + xa = xrUploadArea.x0; + xb = xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + offsetScreenUpload(Position); + + //glRasterPos2f(vertex[0].x,vertex[0].y); + + //glDrawPixels(xrMovieArea.x1-xrMovieArea.x0, + // xrMovieArea.y1-xrMovieArea.y0, + // GL_RGBA,GL_UNSIGNED_BYTE, + LoadDirectMovieFast();//); + + U+=UStep; + } + } + + //----------------------------------------------------// + +// glPixelZoom(1.0F,1.0F); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// + +void UploadScreen(long Position) +{ + short x, y, YStep, XStep, U, s, UStep,ux[4],vy[4]; + short xa,xb,ya,yb; + + if(xrUploadArea.x0>1023) xrUploadArea.x0=1023; + if(xrUploadArea.x1>1024) xrUploadArea.x1=1024; + if(xrUploadArea.y0>iGPUHeightMask) xrUploadArea.y0=iGPUHeightMask; + if(xrUploadArea.y1>iGPUHeight) xrUploadArea.y1=iGPUHeight; + + if(xrUploadArea.x0==xrUploadArea.x1) return; + if(xrUploadArea.y0==xrUploadArea.y1) return; + + if(PSXDisplay.Disabled && iOffscreenDrawing<4) return; + + iDrawnSomething = 2; + iLastRGB24=PSXDisplay.RGB24+1; + + if(bSkipNextFrame) return; + + if(dwActFixes & 2) {UploadScreenEx(Position);return;} + + bUsingMovie = TRUE; + bDrawTextured = TRUE; // just doing textures + bDrawSmoothShaded = FALSE; + +/* if(bGLBlend) vertex[0].c.lcol=0xff7f7f7f; // set solid col + else */vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + SetOGLDisplaySettings(0); + + YStep = 256; // max texture size + XStep = 256; + + UStep = (PSXDisplay.RGB24 ? 128 : 0); + + ya=xrUploadArea.y0; + yb=xrUploadArea.y1; + xa=xrUploadArea.x0; + xb=xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + s=ux[2] - ux[0]; if(s>255) s=255; + + gl_ux[2] = gl_ux[1] = s; + s=vy[2] - vy[0]; if(s>255) s=255; + gl_vy[2] = gl_vy[3] = s; + gl_ux[0] = gl_ux[3] = gl_vy[0] = gl_vy[1] = 0; + + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); // upload texture data + offsetScreenUpload(Position); + assignTextureVRAMWrite(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + U+=UStep; + } + } + + bUsingMovie=FALSE; // done... + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// Detect next screen +//////////////////////////////////////////////////////////////////////// + +BOOL IsCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=y; + if (y >= PSXDisplay.DisplayPosition.y && + y <= PSXDisplay.DisplayEnd.y ) + { + if ((yoff) >= PSXDisplay.DisplayPosition.y && + (yoff) <= PSXDisplay.DisplayEnd.y ) return TRUE; + } + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsPrimCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + x+=PSXDisplay.DrawOffset.x; + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + y+=PSXDisplay.DrawOffset.y; + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + xoff+=PSXDisplay.DrawOffset.x; + if (xoff < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=PSXDisplay.DrawOffset.y; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayEnd.x) return FALSE; + if (y > PSXDisplay.DisplayEnd.y) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayPosition.x) return FALSE; + if ((y + yoff) < PSXDisplay.DisplayPosition.y) return FALSE; + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// mask stuff... +//////////////////////////////////////////////////////////////////////// + +//Mask1 Set mask bit while drawing. 1 = on +//Mask2 Do not draw to mask areas. 1= on + +void cmdSTP(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + STATUSREG&=~0x1800; // clear the necessary bits + STATUSREG|=((gdata & 0x03) << 11); // set the current bits + + if(!iUseMask) return; + + if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;iSetMask=1;} + else {sSetMask=0; lSetMask=0; iSetMask=0;} + + if(gdata&2) + { + if(!(gdata&1)) iSetMask=2; + bCheckMask=TRUE; + if(iDepthFunc==0) return; + iDepthFunc=0; + glDepthFunc(GL_LESS); + } + else + { + bCheckMask=FALSE; + if(iDepthFunc==1) return; + glDepthFunc(GL_ALWAYS); + iDepthFunc=1; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + UpdateGlobalTP((unsigned short)gdata); + GlobalTextREST = (gdata&0x00ffffff)>>9; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: turn on/off texture window +//////////////////////////////////////////////////////////////////////// + +void cmdTextureWindow(u8 *baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + unsigned long YAlign,XAlign; + + ulGPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + if(gdata & 0x020) + TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + TWin.Position.y1 = 128; // 10000 + else + TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + TWin.Position.x1 = 128; // 10000 + else + TWin.Position.x1 = 256; // 00000 + + // Re-calculate the bit field, because we can't trust what is passed in the data + + YAlign = (unsigned long)(32 - (TWin.Position.y1 >> 3)); + XAlign = (unsigned long)(32 - (TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); + TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); + + if((TWin.Position.x0 == 0 && // tw turned off + TWin.Position.y0 == 0 && + TWin.Position.x1 == 0 && + TWin.Position.y1 == 0) || + (TWin.Position.x1 == 256 && + TWin.Position.y1 == 256)) + { + bUsingTWin = FALSE; // -> just do it + +#ifdef OWNSCALE + TWin.UScaleFactor = 1.0f; + TWin.VScaleFactor = 1.0f; +#else + TWin.UScaleFactor = + TWin.VScaleFactor = 1.0f/256.0f; +#endif + } + else // tw turned on + { + bUsingTWin = TRUE; + + TWin.OPosition.y1 = TWin.Position.y1; // -> get psx sizes + TWin.OPosition.x1 = TWin.Position.x1; + + if(TWin.Position.x1<=2) TWin.Position.x1=2; // -> set OGL sizes + else + if(TWin.Position.x1<=4) TWin.Position.x1=4; + else + if(TWin.Position.x1<=8) TWin.Position.x1=8; + else + if(TWin.Position.x1<=16) TWin.Position.x1=16; + else + if(TWin.Position.x1<=32) TWin.Position.x1=32; + else + if(TWin.Position.x1<=64) TWin.Position.x1=64; + else + if(TWin.Position.x1<=128) TWin.Position.x1=128; + else + if(TWin.Position.x1<=256) TWin.Position.x1=256; + + if(TWin.Position.y1<=2) TWin.Position.y1=2; + else + if(TWin.Position.y1<=4) TWin.Position.y1=4; + else + if(TWin.Position.y1<=8) TWin.Position.y1=8; + else + if(TWin.Position.y1<=16) TWin.Position.y1=16; + else + if(TWin.Position.y1<=32) TWin.Position.y1=32; + else + if(TWin.Position.y1<=64) TWin.Position.y1=64; + else + if(TWin.Position.y1<=128) TWin.Position.y1=128; + else + if(TWin.Position.y1<=256) TWin.Position.y1=256; + +#ifdef OWNSCALE + TWin.UScaleFactor = (float)TWin.Position.x1; + TWin.VScaleFactor = (float)TWin.Position.y1; +#else + TWin.UScaleFactor = ((float)TWin.Position.x1)/256.0f; // -> set scale factor + TWin.VScaleFactor = ((float)TWin.Position.y1)/256.0f; +#endif + } +} + +//////////////////////////////////////////////////////////////////////// +// mmm, Lewpy uses that in TileS ... I don't ;) +//////////////////////////////////////////////////////////////////////// + +/* +void ClampToPSXDrawAreaOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < PSXDisplay.DrawArea.x0) + { + *x1 -= (PSXDisplay.DrawArea.x0 - *x0); + *x0 = PSXDisplay.DrawArea.x0; + } + else + if (*x0 > PSXDisplay.DrawArea.x1) + { + *x0 = PSXDisplay.DrawArea.x1; + *x1 = 0; + } + + if (*y0 < PSXDisplay.DrawArea.y0) + { + *y1 -= (PSXDisplay.DrawArea.y0 - *y0); + *y0 = PSXDisplay.DrawArea.y0; + } + else + if (*y0 > PSXDisplay.DrawArea.y1) + { + *y0 = PSXDisplay.DrawArea.y1; + *y1 = 0; + } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > PSXDisplay.DrawArea.x1) + *x1 = (PSXDisplay.DrawArea.x1 - *x0 + 1); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > PSXDisplay.DrawArea.y1) + *y1 = (PSXDisplay.DrawArea.y1 - *y0 + 1); +} +*/ + +//////////////////////////////////////////////////////////////////////// +// Check draw area dimensions +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreen(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) *x0 = 0; + else + if (*x0 > 1023) *x0 = 1023; + + if (*x1 < 0) *x1 = 0; + else + if (*x1 > 1023) *x1 = 1023; + + if (*y0 < 0) *y0 = 0; + else + if (*y0 > iGPUHeightMask) *y0 = iGPUHeightMask; + + if (*y1 < 0) *y1 = 0; + else + if (*y1 > iGPUHeightMask) *y1 = iGPUHeightMask; +} + +//////////////////////////////////////////////////////////////////////// +// Used in Load Image and Blk Fill +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreenOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) + { *x1 += *x0; *x0 = 0; } + else + if (*x0 > 1023) + { *x0 = 1023; *x1 = 0; } + + if (*y0 < 0) + { *y1 += *y0; *y0 = 0; } + else + if (*y0 > iGPUHeightMask) + { *y0 = iGPUHeightMask; *y1 = 0; } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > 1024) *x1 = (1024 - *x0); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > iGPUHeight) *y1 = (iGPUHeight - *y0); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: start of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaStart(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + drawX = gdata & 0x3ff; // for soft drawing + if(drawX>=1024) drawX=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + drawY = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; + drawY = (gdata>>10)&0x3ff; + } + + if(drawY>=iGPUHeight) drawY=iGPUHeightMask; + + PreviousPSXDisplay.DrawArea.y0=PSXDisplay.DrawArea.y0; + PreviousPSXDisplay.DrawArea.x0=PSXDisplay.DrawArea.x0; + + PSXDisplay.DrawArea.y0 = (short)drawY; // for OGL drawing + PSXDisplay.DrawArea.x0 = (short)drawX; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: end of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaEnd(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + drawW = gdata & 0x3ff; // for soft drawing + if(drawW>=1024) drawW=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + drawH = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; + drawH = (gdata>>10)&0x3ff; + } + + if(drawH>=iGPUHeight) drawH=iGPUHeightMask; + + PSXDisplay.DrawArea.y1 = (short)drawH; // for OGL drawing + PSXDisplay.DrawArea.x1 = (short)drawW; + + ClampToPSXScreen(&PSXDisplay.DrawArea.x0, // clamp + &PSXDisplay.DrawArea.y0, + &PSXDisplay.DrawArea.x1, + &PSXDisplay.DrawArea.y1); + + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw offset... will be added to prim coords +//////////////////////////////////////////////////////////////////////// + +void cmdDrawOffset(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + PreviousPSXDisplay.DrawOffset.x = + PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); + } + else + { + ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); + } + + PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); + PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); + + PSXDisplay.CumulOffset.x = // new OGL prim offsets + PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = + PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(u8 * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMWrite.x = sgpuData[2]&0x03ff; + VRAMWrite.y = sgpuData[3]&iGPUHeightMask; + VRAMWrite.Width = sgpuData[4]; + VRAMWrite.Height = sgpuData[5]; + + iDataWriteMode = DR_VRAMTRANSFER; + VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining = VRAMWrite.Height; + + bNeedWriteUpload=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareRGB24Upload(void) +{ + VRAMWrite.x=(VRAMWrite.x*2)/3; + VRAMWrite.Width=(VRAMWrite.Width*2)/3; + + if(!PSXDisplay.InterlacedTest && // NEW + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PreviousPSXDisplay.DisplayPosition.y; + } + else + if(CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PSXDisplay.DisplayPosition.y; + } + else return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + if(bNeedRGB24Update==FALSE) + { + xrUploadAreaRGB24=xrUploadArea; + bNeedRGB24Update=TRUE; + } + else + { + xrUploadAreaRGB24.x0=min(xrUploadAreaRGB24.x0,xrUploadArea.x0); + xrUploadAreaRGB24.x1=max(xrUploadAreaRGB24.x1,xrUploadArea.x1); + xrUploadAreaRGB24.y0=min(xrUploadAreaRGB24.y0,xrUploadArea.y0); + xrUploadAreaRGB24.y1=max(xrUploadAreaRGB24.y1,xrUploadArea.y1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CheckWriteUpdate() +{ + int iX=0,iY=0; + + if(VRAMWrite.Width) iX=1; + if(VRAMWrite.Height) iY=1; + + InvalidateTextureArea(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width-iX, VRAMWrite.Height-iY); + + if(PSXDisplay.Interlaced && !iOffscreenDrawing) return; + + if(PSXDisplay.RGB24) {PrepareRGB24Upload();return;} + + if(!PSXDisplay.InterlacedTest && + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(dwActFixes&0x800) return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + UploadScreen(FALSE); + + bNeedUploadTest=TRUE; + } + else + if(iOffscreenDrawing) + { + if (CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(PSXDisplay.InterlacedTest) + { + if(PreviousPSXDisplay.InterlacedNew) + { + PreviousPSXDisplay.InterlacedNew=FALSE; + bNeedInterlaceUpdate=TRUE; + xrUploadAreaIL.x0=PSXDisplay.DisplayPosition.x; + xrUploadAreaIL.y0=PSXDisplay.DisplayPosition.y; + xrUploadAreaIL.x1=PSXDisplay.DisplayPosition.x+PSXDisplay.DisplayModeNew.x; + xrUploadAreaIL.y1=PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayModeNew.y; + if(xrUploadAreaIL.x1>1023) xrUploadAreaIL.x1=1023; + if(xrUploadAreaIL.y1>511) xrUploadAreaIL.y1=511; + } + + if(bNeedInterlaceUpdate==FALSE) + { + xrUploadAreaIL=xrUploadArea; + bNeedInterlaceUpdate=TRUE; + } + else + { + xrUploadAreaIL.x0=min(xrUploadAreaIL.x0,xrUploadArea.x0); + xrUploadAreaIL.x1=max(xrUploadAreaIL.x1,xrUploadArea.x1); + xrUploadAreaIL.y0=min(xrUploadAreaIL.y0,xrUploadArea.y0); + xrUploadAreaIL.y1=max(xrUploadAreaIL.y1,xrUploadArea.y1); + } + return; + } + + if(!bNeedUploadAfter) + { + bNeedUploadAfter = TRUE; + xrUploadArea.x0=VRAMWrite.x; + xrUploadArea.x1=VRAMWrite.x+VRAMWrite.Width; + xrUploadArea.y0=VRAMWrite.y; + xrUploadArea.y1=VRAMWrite.y+VRAMWrite.Height; + } + else + { + xrUploadArea.x0=min(xrUploadArea.x0,VRAMWrite.x); + xrUploadArea.x1=max(xrUploadArea.x1,VRAMWrite.x+VRAMWrite.Width); + xrUploadArea.y0=min(xrUploadArea.y0,VRAMWrite.y); + xrUploadArea.y1=max(xrUploadArea.y1,VRAMWrite.y+VRAMWrite.Height); + } + + if(dwActFixes&0x8000) + { + if((xrUploadArea.x1-xrUploadArea.x0)>=(PSXDisplay.DisplayMode.x-32) && + (xrUploadArea.y1-xrUploadArea.y0)>=(PSXDisplay.DisplayMode.y-32)) + { + UploadScreen(-1); + updateFrontDisplay(); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(u8 * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMRead.x = sgpuData[2]&0x03ff; + VRAMRead.y = sgpuData[3]&iGPUHeightMask; + VRAMRead.Width = sgpuData[4]; + VRAMRead.Height = sgpuData[5]; + + VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining = VRAMRead.Height; + + iDataReadMode = DR_VRAMTRANSFER; + + STATUSREG |= GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: blkfill - NO primitive! Doesn't care about draw areas... +//////////////////////////////////////////////////////////////////////// + +void primBlkFill(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + iDrawnSomething=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[4] & 0x3ff; + sprtH = sgpuData[5] & iGPUHeightMask; + + sprtW = (sprtW+15) & ~15; + + // Increase H & W if they are one short of full values, because they never can be full values + if (sprtH == iGPUHeightMask) sprtH=iGPUHeight; + if (sprtW == 1023) sprtW=1024; + + // x and y of start + ly0 = ly1 = sprtY; + ly2 = ly3 = (sprtY+sprtH); + lx0 = lx3 = sprtX; + lx1 = lx2 = (sprtX+sprtW); + + offsetBlk(); + + if(ClipVertexListScreen()) + { + PSXDisplay_t * pd; + if(PSXDisplay.InterlacedTest) pd=&PSXDisplay; + else pd=&PreviousPSXDisplay; + + if ((lx0 <= pd->DisplayPosition.x+16) && + (ly0 <= pd->DisplayPosition.y+16) && + (lx2 >= pd->DisplayEnd.x-16) && + (ly2 >= pd->DisplayEnd.y-16)) + { + GLclampf g,b,r; + g=((GLclampf)GREEN(gpuData[0]))/255.0f; + b=((GLclampf)BLUE(gpuData[0]))/255.0f; + r=((GLclampf)RED(gpuData[0]))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,1.0f); + glClear(uiBufferBits); + gl_z=0.0f; + + if(gpuData[0]!=0x02000000 && + (ly0>pd->DisplayPosition.y || + ly2DisplayEnd.y)) + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); + vertex[0].c.lcol=0xff000000; + SETCOL(vertex[0]); + if(ly0>pd->DisplayPosition.y) + { + vertex[0].x=0;vertex[0].y=0; + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=0; + vertex[2].x=vertex[1].x;vertex[2].y=ly0-pd->DisplayPosition.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + if(ly2DisplayEnd.y) + { + vertex[0].x=0;vertex[0].y=(pd->DisplayEnd.y-pd->DisplayPosition.y)-(pd->DisplayEnd.y-ly2); + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=vertex[0].y; + vertex[2].x=vertex[1].x;vertex[2].y=pd->DisplayEnd.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + } + + glEnable(GL_SCISSOR_TEST); + } + else + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); + vertex[0].c.lcol=gpuData[0]|0xff000000; + SETCOL(vertex[0]); + glDisable(GL_SCISSOR_TEST); + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glEnable(GL_SCISSOR_TEST); + } + } + + //mmm... will clean all stuff, also if not all _should_ be cleaned... + //if (IsInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + // try this: + if (IsCompleteInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + { + lClearOnSwapColor = COLOR(gpuData[0]); + lClearOnSwap = 1; + } + +/* if(iOffscreenDrawing) + { + ClampToPSXScreenOffset( &sprtX, &sprtY, &sprtW, &sprtH); + if ((sprtW == 0) || (sprtH == 0)) return; + InvalidateTextureArea(sprtX, sprtY, sprtW-1, sprtH-1); + + sprtW+=sprtX; + sprtH+=sprtY; + + FillSoftwareArea(sprtX, sprtY, sprtW, sprtH, BGR24to16(gpuData[0])); + }*/ +} + +//////////////////////////////////////////////////////////////////////// +// cmd: move image vram -> vram +//////////////////////////////////////////////////////////////////////// + +void MoveImageWrapped(short imageX0,short imageY0, + short imageX1,short imageY1, + short imageSX,short imageSY) +{ + int i,j,imageXE,imageYE; + + if(iFrameReadType&2) + { + imageXE=imageX0+imageSX; + imageYE=imageY0+imageSY; + + if(imageYE>iGPUHeight && imageXE>1024) + { + CheckVRamRead(0,0, + (imageXE&0x3ff), + (imageY0&iGPUHeightMask), + FALSE); + } + + if(imageXE>1024) + { + CheckVRamRead(0,imageY0, + (imageXE&0x3ff), + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + if(imageYE>iGPUHeight) + { + CheckVRamRead(imageX0,0, + (imageXE>1024)?1024:imageXE, + imageYE&iGPUHeightMask, + FALSE); + } + + CheckVRamRead(imageX0,imageY0, + (imageXE>1024)?1024:imageXE, + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + for(j=0;jiGPUHeight && imageXE>1024) + { + InvalidateTextureArea(0,0, + (imageXE&0x3ff)-1, + (imageYE&iGPUHeightMask)-1); + } + + if(imageXE>1024) + { + InvalidateTextureArea(0,imageY1, + (imageXE&0x3ff)-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } + + if(imageYE>iGPUHeight) + { + InvalidateTextureArea(imageX1,0, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + (imageYE&iGPUHeightMask)-1); + } + + InvalidateTextureArea(imageX1,imageY1, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void primMoveImage(u8 * baseAddr) +{ + short *sgpuData = ((short *) baseAddr); + short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; + + imageX0 = sgpuData[2]&0x03ff; + imageY0 = sgpuData[3]&iGPUHeightMask; + imageX1 = sgpuData[4]&0x03ff; + imageY1 = sgpuData[5]&iGPUHeightMask; + imageSX = sgpuData[6]; + imageSY = sgpuData[7]; + + if((imageX0 == imageX1) && (imageY0 == imageY1)) return; + if(imageSX<=0) return; + if(imageSY<=0) return; + + if(iGPUHeight==1024 && sgpuData[7]>1024) return; + + if((imageY0+imageSY)>iGPUHeight || + (imageX0+imageSX)>1024 || + (imageY1+imageSY)>iGPUHeight || + (imageX1+imageSX)>1024) + { + MoveImageWrapped(imageX0,imageY0,imageX1,imageY1,imageSX,imageSY); + if((imageY0+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY0; + if((imageX0+imageSX)>1024) imageSX=1024-imageX0; + if((imageY1+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY1; + if((imageX1+imageSX)>1024) imageSX=1024-imageX1; + } + + if(iFrameReadType&2) + CheckVRamRead(imageX0,imageY0, + imageX0+imageSX, + imageY0+imageSY, + FALSE); + + if(imageSX&1) + { + unsigned short *SRCPtr, *DSTPtr; + unsigned short LineOffset; + + SRCPtr = psxVuw + (1024*imageY0) + imageX0; + DSTPtr = psxVuw + (1024*imageY1) + imageX1; + + LineOffset = 1024 - imageSX; + + for(j=0;j>1; + + SRCPtr = (unsigned long *)(psxVuw + (1024*imageY0) + imageX0); + DSTPtr = (unsigned long *)(psxVuw + (1024*imageY1) + imageX1); + + LineOffset = 512 - dx; + + for(j=0;j=PreviousPSXDisplay.DisplayPosition.x && + imageX1=PreviousPSXDisplay.DisplayPosition.y && + imageY1=PreviousPSXDisplay.DisplayPosition.x && + imageX1<=PreviousPSXDisplay.DisplayEnd.x && + imageY1>=PreviousPSXDisplay.DisplayPosition.y && + imageY1<=PreviousPSXDisplay.DisplayEnd.y) + { + if(!( + imageX0>=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0=PreviousPSXDisplay.DisplayPosition.x && + imageX0=PreviousPSXDisplay.DisplayPosition.y && + imageY0=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0 set color with + SETCOL(vertex[0]); // texture alpha + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + vertex[0].x+=POFF;vertex[1].x+=POFF; + vertex[2].x+=POFF;vertex[3].x+=POFF; + vertex[0].y+=POFF;vertex[1].y+=POFF; + vertex[2].y+=POFF;vertex[3].y+=POFF; + GlobalTextABR=0; + DrawSemiTrans=1; + SetSemiTrans(); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + GlobalTextABR=lABR; + DrawSemiTrans=lDST; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 8; + sprtH = 8; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); + else + DrawSoftwareSprite(baseAddr,8,8,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 16; + sprtH = 16; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); + else + DrawSoftwareSprite(baseAddr,16,16,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: free-size sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprtSRest(u8 * baseAddr,unsigned short type) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s;unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + + // do texture stuff + switch(type) + { + case 1: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 2: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 3: + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + case 4: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 5: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 6: + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + } + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1;if(s<0) s=0; + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1;if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + if(sTypeRest && type<4) + { + if(sTypeRest&1 && type==1) primSprtSRest(baseAddr,4); + if(sTypeRest&2 && type==2) primSprtSRest(baseAddr,5); + if(sTypeRest==3 && type==3) primSprtSRest(baseAddr,6); + } +} + +void primSprtS(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + short s;unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + if(!sprtH) return; + if(!sprtW) return; + + iSpriteTex=1; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + if((dwActFixes&1) && gTexFrameName && gTexName==gTexFrameName) + {iSpriteTex=0;return;} + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + if(sTypeRest) + { + if(sTypeRest&1) primSprtSRest(baseAddr,1); + if(sTypeRest&2) primSprtSRest(baseAddr,2); + if(sTypeRest==3) primSprtSRest(baseAddr,3); + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + lx3 = sgpuData[8]; + ly3 = sgpuData[9]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0];vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri2(&vertex[0], &vertex[1], &vertex[2],&vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(u8 * baseAddr); + +BOOL bDrawOffscreenFrontFF9G4(void) +{ + if(lx0< PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(lx0> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly0< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly0> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx1< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx1> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly1< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly1> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx2< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx2> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly2< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly2> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx3< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx3> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly3< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly3> PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bCheckFF9G4(u8 * baseAddr) +{ + static u8 pFF9G4Cache[32]; + static int iFF9Fix=0; + + if(baseAddr) + { + if(iFF9Fix==0) + { + if(bDrawOffscreenFrontFF9G4()) + { + short *sgpuData = ((short *) pFF9G4Cache); + iFF9Fix=2; + memcpy(pFF9G4Cache,baseAddr,32); + + if(sgpuData[2]==142) + { + sgpuData[2] +=65; + sgpuData[10]+=65; + } + return TRUE; + } + else iFF9Fix=1; + } + return FALSE; + } + + if(iFF9Fix==2) + { + long labr=GlobalTextABR; + GlobalTextABR=1; + primPolyG4(pFF9G4Cache); + GlobalTextABR=labr; + } + iFF9Fix=0; + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(u8 * baseAddr) +{ + unsigned long *gpuData = (unsigned long *)baseAddr; + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if((dwActFixes&512) && bCheckFF9G4(baseAddr)) return; + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0], gpuData[2], gpuData[4], gpuData[6]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[3].c.lcol=gpuData[6]; + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + + PRIMdrawGouraudTri2Color(&vertex[0],&vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +BOOL DoLineCheck(unsigned long * gpuData) +{ + BOOL bQuad=FALSE;short dx,dy; + + if(lx0==lx1) + { + dx=lx0-lx2;if(dx<0) dx=-dx; + + if(ly1==ly2) + { + dy=ly1-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly2) + { + dy=ly0-ly1;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[3].x=vertex[2].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[3].y=vertex[1].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx0==lx2) + { + dx=lx0-lx1;if(dx<0) dx=-dx; + + if(ly2==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[3].x=vertex[1].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[3].y=vertex[2].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx1==lx2) + { + dx=lx1-lx0;if(dx<0) dx=-dx; + + if(ly1==ly0) + { + dy=ly1-ly2;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly2==ly0) + { + dy=ly2-ly1;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(!bQuad) return FALSE; + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + // do texture UV coordinates stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[16];//gpuData[4]&0xff; + gl_vy[1]=baseAddr[17];//(gpuData[4]>>8)&0xff; + gl_ux[2]=baseAddr[24];//gpuData[6]&0xff; + gl_vy[2]=baseAddr[25];//(gpuData[6]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=gpuData[2]>>16; + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly3FT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask3(); + + assignTexture3(); + + if(!(dwActFixes&0x10)) + { + if(DoLineCheck(gpuData)) return; + } + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +#define ST_FAC 255.99f + +void RectTexAlign(void) +{ + int UFlipped = FALSE; + int VFlipped = FALSE; + + if(gTexName==gTexFrameName) return; + + if(ly0==ly1) + { + if(!((lx1==lx3 && ly3==ly2 && lx2==lx0) || + (lx1==lx2 && ly2==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[2].tow) + VFlipped = 1; + } + else + { + if (vertex[0].tow < vertex[2].tow) + VFlipped = 2; + } + } + else + if(ly0==ly2) + { + if(!((lx2==lx3 && ly3==ly1 && lx1==lx0) || + (lx2==lx1 && ly1==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 3; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 4; + } + } + else + if(ly0==ly3) + { + if(!((lx3==lx2 && ly2==ly1 && lx1==lx0) || + (lx3==lx1 && ly1==ly2 && lx2==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 5; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 6; + } + } + else return; + + if(lx0==lx1) + { + if(lx0 vertex[2].sow) + UFlipped = 1; + } + else + { + if (vertex[0].sow < vertex[2].sow) + UFlipped = 2; + } + } + else + if(lx0==lx2) + { + if(lx0 vertex[1].sow) + UFlipped = 3; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 4; + } + } + else + if(lx0==lx3) + { + if(lx0 vertex[1].sow) + UFlipped = 5; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 6; + } + } + + if (UFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[1].sow+=0.95f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].sow+=1.0f/ST_FAC; + vertex[1].sow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[1].sow+=1.0f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 2: + vertex[0].sow+=1.0f; + vertex[1].sow+=1.0f; + break; + case 3: + vertex[1].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 4: + vertex[0].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 5: + vertex[1].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 6: + vertex[0].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + } + } +#endif + } + + if (VFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[1].tow+=0.95f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].tow+=1.0f/ST_FAC; + vertex[1].tow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[1].tow+=1.0f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 2: + vertex[0].tow+=1.0f; + vertex[1].tow+=1.0f; + break; + case 3: + vertex[1].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 4: + vertex[0].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 5: + vertex[1].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 6: + vertex[0].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + } + } +#endif + } + +} + +void primPolyFT4(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + gl_vy[0]=baseAddr[9];//((gpuData[2]>>8)&0xff); + gl_vy[1]=baseAddr[17];//((gpuData[4]>>8)&0xff); + gl_vy[2]=baseAddr[25];//((gpuData[6]>>8)&0xff); + gl_vy[3]=baseAddr[33];//((gpuData[8]>>8)&0xff); + + gl_ux[0]=baseAddr[8];//(gpuData[2]&0xff); + gl_ux[1]=baseAddr[16];//(gpuData[4]&0xff); + gl_ux[2]=baseAddr[24];//(gpuData[6]&0xff); + gl_ux[3]=baseAddr[32];//(gpuData[8]&0xff); + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly4FT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + + if(offset3()) return; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3GT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3(); + + assignTexture3(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; + // eat this... +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else */vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask3O(); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + +/* if(!bUseMultiPass && !bGLBlend) + { + */ vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + /*} + else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + }*/ + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + } + DEFOPAQUEON + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3G(gpuData[0], gpuData[2], gpuData[4]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloColAlpha; + + PRIMdrawGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + lx3 = sgpuData[20]; + ly3 = sgpuData[21]; + + if(offset4()) return; + + // do texture stuff + gl_ux[0]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + gl_ux[3]=baseAddr[44];//gpuData[11]&0xff; + gl_vy[3]=baseAddr[45];//(gpuData[11]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4GT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else */vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask4O(); + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + +// if(!bUseMultiPass && !bGLBlend) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + } + /*else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + vertex[3].c.lcol=gpuData[9]; + }*/ + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + } + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3F(gpuData[0]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + int iMax=255; + int i=2; + + lx1 = sgpuData[2]; + ly1 = sgpuData[3]; + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGEx(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int iMax=255; + short cx0,cx1,cy0,cy1;int i;BOOL bDraw=TRUE; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + + //while((gpuData[i]>>24)!=0x55) + //while((gpuData[i]&0x50000000)!=0x50000000) + // currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + ly0 = ly1;lx0=lx1; + vertex[1].c.lcol=vertex[2].c.lcol=vertex[0].c.lcol; + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[i]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(offsetline()) bDraw=FALSE; else bDraw=TRUE; + + if (bDraw && ((lx0 != lx1) || (ly0 != ly1))) + { +/* if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[i-3],gpuData[i-1],gpuData[i-3],gpuData[i-1]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + }*/ + + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + i++; + + if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[1].c.lcol=vertex[2].c.lcol=gpuData[2]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + + if((lx0 == lx1) && (ly0 == ly1)) return; + + if(offsetline()) return; + + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + +/* if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0],gpuData[2],gpuData[0],gpuData[2]); + } + } +*/ + //if(ClipVertexList4()) + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int i=2,iMax=255; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFEx(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int iMax; + short cx0,cx1,cy0,cy1;int i; + + iMax=255; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + +// while(!(gpuData[i]&0x40000000)) +// while((gpuData[i]>>24)!=0x55) +// while((gpuData[i]&0x50000000)!=0x50000000) +// currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly0 = ly1;lx0=lx1; + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(!offsetline()) + { +/* if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + }*/ + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + i++;if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + + if(offsetline()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + +/* if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } +*/ + //if(ClipVertexList4()) + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(u8 *bA) +{ +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + +void (*primTableJ[256])(u8 *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table for skipping +//////////////////////////////////////////////////////////////////////// + +void (*primTableSkip[256])(u8 *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 28 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 30 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 38 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 40 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 48 + primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, + // 50 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 58 + primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, + // 60 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 78 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; diff --git a/plugins/gpu-gles/gpuPrim.h b/plugins/gpu-gles/gpuPrim.h new file mode 100644 index 00000000..58d33118 --- /dev/null +++ b/plugins/gpu-gles/gpuPrim.h @@ -0,0 +1,58 @@ +/*************************************************************************** + prim.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _PRIMDRAW_H_ +#define _PRIMDRAW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gpuExternals.h" +#include "gpuStdafx.h" + +#ifndef _WINDOWS +extern EGLSurface surface; +extern EGLDisplay display; +#endif + +void UploadScreen (long Position); +void PrepareFullScreenUpload (long Position); +BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL bCheckFF9G4(u8 * baseAddr); +void SetScanTrans(void); +void SetScanTexTrans(void); +void DrawMultiBlur(void); +void CheckWriteUpdate(); + +#ifdef __cplusplus +} +#endif + +#endif // _PRIMDRAW_H_ diff --git a/plugins/gpu-gles/gpuStdafx.h b/plugins/gpu-gles/gpuStdafx.h new file mode 100644 index 00000000..fc7ee3d5 --- /dev/null +++ b/plugins/gpu-gles/gpuStdafx.h @@ -0,0 +1,99 @@ +/*************************************************************************** + stdafx.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef __GPU_STDAFX__ +#define __GPU_STDAFX__ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + // maybe we should remove this? +#ifdef _WINDOWS + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include "resource.h" + +#pragma warning (disable:4244) + +#include + +#else +/* +#define __X11_C_ +*/ + +#include +#include +#include +#include +#ifdef __NANOGL__ +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifdef MAEMO_CHANGES + #include + #include + #include + #include +#else + #include // for opengl es types + #include +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#include + +#define __inline inline + +#endif + +#define SHADETEXBIT(x) ((x>>24) & 0x1) +#define SEMITRANSBIT(x) ((x>>25) & 0x1) + +#ifndef _WINDOWS +#ifndef GL_BGRA_EXT +#define GL_BGRA_EXT GL_RGBA +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/gpu-gles/gpuTexture.c b/plugins/gpu-gles/gpuTexture.c new file mode 100644 index 00000000..d047a62f --- /dev/null +++ b/plugins/gpu-gles/gpuTexture.c @@ -0,0 +1,4226 @@ +/*************************************************************************** + texture.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.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. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +//////////////////////////////////////////////////////////////////////////////////// +// Texture related functions are here ! +// +// The texture handling is heart and soul of this gpu. The plugin was developed +// 1999, by this time no shaders were available. Since the psx gpu is making +// heavy use of CLUT (="color lookup tables", aka palettized textures), it was +// an interesting task to get those emulated at good speed on NV TNT cards +// (which was my major goal when I created the first "gpuPeteTNT"). Later cards +// (Geforce256) supported texture palettes by an OGL extension, but at some point +// this support was dropped again by gfx card vendors. +// Well, at least there is a certain advatage, if no texture palettes extension can +// be used: it is possible to modify the textures in any way, allowing "hi-res" +// textures and other tweaks. +// +// My main texture caching is kinda complex: the plugin is allocating "n" 256x256 textures, +// and it places small psx texture parts inside them. The plugin keeps track what +// part (with what palette) it had placed in which texture, so it can re-use this +// part again. The more ogl textures it can use, the better (of course the managing/ +// searching will be slower, but everything is faster than uploading textures again +// and again to a gfx card). My first card (TNT1) had 16 MB Vram, and it worked +// well with many games, but I recommend nowadays 64 MB Vram to get a good speed. +// +// Sadly, there is also a second kind of texture cache needed, for "psx texture windows". +// Those are "repeated" textures, so a psx "texture window" needs to be put in +// a whole texture to use the GL_TEXTURE_WRAP_ features. This cache can get full very +// fast in games which are having an heavy "texture window" usage, like RRT4. As an +// alternative, this plugin can use the OGL "palette" extension on texture windows, +// if available. Nowadays also a fragment shader can easily be used to emulate +// texture wrapping in a texture atlas, so the main cache could hold the texture +// windows as well (that's what I am doing in the OGL2 plugin). But currently the +// OGL1 plugin is a "shader-free" zone, so heavy "texture window" games will cause +// much texture uploads. +// +// Some final advice: take care if you change things in here. I've removed my ASM +// handlers (they didn't cause much speed gain anyway) for readability/portability, +// but still the functions/data structures used here are easy to mess up. I guess it +// can be a pain in the ass to port the plugin to another byte order :) +// +//////////////////////////////////////////////////////////////////////////////////// + +#define _IN_TEXTURE + +#ifdef _WINDOWS +#include "stdafx.h" + +#include "externals.h" +#include "texture.h" +#include "gpu.h" +#include "prim.h" +#else +#include "gpuStdafx.h" +#ifdef __NANOGL__ +#include +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifdef MAEMO_CHANGES + #include + #include + #include + #include +#else + #include // for opengl es types + #include +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#include "gpuDraw.h" +//#include "plugins.h" +#include "gpuExternals.h" +#include "gpuTexture.h" +#include "gpuPlugin.h" +#include "gpuPrim.h" +#endif +#define CLUTCHK 0x00060000 +#define CLUTSHIFT 17 + +//////////////////////////////////////////////////////////////////////// +// texture conversion buffer .. +//////////////////////////////////////////////////////////////////////// + +GLubyte ubPaletteBuffer[256][4]; +GLuint gTexMovieName=0; +GLuint gTexBlurName=0; +GLuint gTexFrameName=0; +int iTexGarbageCollection=1; +unsigned long dwTexPageComp=0; +int iVRamSize=0; +#ifdef _WINDOWS +int iClampType=GL_CLAMP; +#else +int iClampType=GL_CLAMP_TO_EDGE; +#endif +int iFilter = GL_LINEAR; +void (*LoadSubTexFn) (int,int,short,short); +unsigned long (*PalTexturedColourFn) (unsigned long); + +//////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////// + +#define PALCOL(x) PalTexturedColourFn (x) + +#define CSUBSIZE 2048 +#define CSUBSIZEA 8192 +#define CSUBSIZES 4096 + +#define OFFA 0 +#define OFFB 2048 +#define OFFC 4096 +#define OFFD 6144 + +#define XOFFA 0 +#define XOFFB 512 +#define XOFFC 1024 +#define XOFFD 1536 + +#define SOFFA 0 +#define SOFFB 1024 +#define SOFFC 2048 +#define SOFFD 3072 + +#define MAXWNDTEXCACHE 128 + +#define XCHECK(pos1,pos2) ((pos1.c[0]>=pos2.c[1])&&(pos1.c[1]<=pos2.c[0])&&(pos1.c[2]>=pos2.c[3])&&(pos1.c[3]<=pos2.c[2])) +#define INCHECK(pos2,pos1) ((pos1.c[0]<=pos2.c[0]) && (pos1.c[1]>=pos2.c[1]) && (pos1.c[2]<=pos2.c[2]) && (pos1.c[3]>=pos2.c[3])) + +//////////////////////////////////////////////////////////////////////// + +u8 * CheckTextureInSubSCache(long TextureMode,unsigned long GivenClutId,unsigned short * pCache); +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy); +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy); +void DefineSubTextureSort(void); + +//////////////////////////////////////////////////////////////////////// +// some globals +//////////////////////////////////////////////////////////////////////// + +long GlobalTexturePage; +GLint XTexS; +GLint YTexS; +GLint DXTexS; +GLint DYTexS; +int iSortTexCnt=32; +BOOL bUseFastMdec=FALSE; +BOOL bUse15bitMdec=FALSE; +int iFrameTexType=0; +int iFrameReadType=0; + +unsigned long (*TCF[2]) (unsigned long); +unsigned short (*PTCF[2]) (unsigned short); + +//////////////////////////////////////////////////////////////////////// +// texture cache implementation +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +#pragma pack(1) +#endif + +// "texture window" cache entry + +typedef struct textureWndCacheEntryTag +{ + unsigned long ClutID; + short pageid; + short textureMode; + short Opaque; + short used; + EXLong pos; + GLuint texname; +} textureWndCacheEntry; + +// "standard texture" cache entry (12 byte per entry, as small as possible... we need lots of them) + +typedef struct textureSubCacheEntryTagS +{ + unsigned long ClutID; + EXLong pos; + u8 posTX; + u8 posTY; + u8 cTexID; + u8 Opaque; +} textureSubCacheEntryS; + +#ifdef _WINDOWS +#pragma pack() +#endif + +//--------------------------------------------- + +#define MAXTPAGES_MAX 64 +#define MAXSORTTEX_MAX 196 + +//--------------------------------------------- + +textureWndCacheEntry wcWndtexStore[MAXWNDTEXCACHE]; +textureSubCacheEntryS * pscSubtexStore[3][MAXTPAGES_MAX]; +EXLong * pxSsubtexLeft [MAXSORTTEX_MAX]; +GLuint uiStexturePage[MAXSORTTEX_MAX]; + +unsigned short usLRUTexPage=0; + +int iMaxTexWnds=0; +int iTexWndTurn=0; +int iTexWndLimit=MAXWNDTEXCACHE/2; + +GLubyte * texturepart=NULL; +GLubyte * texturebuffer=NULL; +unsigned long g_x1,g_y1,g_x2,g_y2; +u8 ubOpaqueDraw=0; + +unsigned short MAXTPAGES = 32; +unsigned short CLUTMASK = 0x7fff; +unsigned short CLUTYMASK = 0x1ff; +unsigned short MAXSORTTEX = 196; + +//////////////////////////////////////////////////////////////////////// +// Texture color conversions... all my ASM funcs are removed for easier +// porting... and honestly: nowadays the speed gain would be pointless +//////////////////////////////////////////////////////////////////////// + +unsigned long XP8RGBA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long CP8RGBA(unsigned long BGR) +{ + unsigned long l; + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +unsigned long CP8RGBAEx(unsigned long BGR) +{ + unsigned long l; + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +unsigned long XP8RGBA_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRA_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRAEx_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long CP8RGBA_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +unsigned long CP8RGBAEx_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +unsigned long CP8BGRA_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +unsigned long CP8BGRAEx_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +unsigned long XP8RGBA_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRA_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRAEx_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long P8RGBA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long P8BGRA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned short XP5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP5RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 0; + + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short CP5RGBA_0 (unsigned short BGR) +{ + unsigned short s; + + if(!BGR) return 0; + + s=((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; + if(s==0x07ff) s=1; + return s; +} + +unsigned short XP5RGBA_1(unsigned short BGR) +{ + if(!BGR) return 0; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short P5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP4RGBA(unsigned short BGR) +{ + if(!BGR) return 6; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short XP4RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 6; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short CP4RGBA_0 (unsigned short BGR) +{ + unsigned short s; + if(!BGR) return 6; + s=(((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; + if(s==0x0fff) s=0x000f; + return s; +} + +unsigned short XP4RGBA_1(unsigned short BGR) +{ + if(!BGR) return 6; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short P4RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +//////////////////////////////////////////////////////////////////////// +// CHECK TEXTURE MEM (on plugin startup) +//////////////////////////////////////////////////////////////////////// + +int iFTexA=512; +int iFTexB=512; + +void CheckTextureMemory(void) +{ + GLboolean b;GLboolean * bDetail; + int i,iCnt,iRam=iVRamSize*1024*1024; + int iTSize;s8 * p; + + + if(iVRamSize) + { + int ts; + + iRam-=(iResX*iResY*8); + iRam-=(iResX*iResY*(iZBufferDepth/8)); + + ts=4; + iSortTexCnt=iRam/(256*256*ts); + + if(iSortTexCnt>MAXSORTTEX) + { + iSortTexCnt=MAXSORTTEX-min(1,0); + } + else + { + iSortTexCnt-=3+min(1,0); + if(iSortTexCnt<8) iSortTexCnt=8; + } + + for(i=0;i info for 32*3 + for(j=0;j info 0..511 + { + pxSsubtexLeft[i]=(EXLong *)malloc(CSUBSIZE*sizeof(EXLong)); + memset(pxSsubtexLeft[i],0,CSUBSIZE*sizeof(EXLong)); + uiStexturePage[i]=0; + } +} + +//////////////////////////////////////////////////////////////////////// +// Clean up on exit +//////////////////////////////////////////////////////////////////////// + +void CleanupTextureStore() +{ + int i,j;textureWndCacheEntry * tsx; + //----------------------------------------------------// + glBindTexture(GL_TEXTURE_2D,0); + //----------------------------------------------------// + free(texturepart); // free tex part + texturepart=0; + if(texturebuffer) + { + free(texturebuffer); + texturebuffer=0; + } + //----------------------------------------------------// + tsx=wcWndtexStore; // loop tex window cache + for(i=0;itexname) // -> some tex? + glDeleteTextures(1,&tsx->texname); // --> delete it + } + iMaxTexWnds=0; // no more tex wnds + //----------------------------------------------------// + if(gTexMovieName!=0) // some movie tex? + glDeleteTextures(1, &gTexMovieName); // -> delete it + gTexMovieName=0; // no more movie tex + //----------------------------------------------------// + if(gTexFrameName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexFrameName); // -> delete it + gTexFrameName=0; // no more movie tex + //----------------------------------------------------// + if(gTexBlurName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexBlurName); // -> delete it + gTexBlurName=0; // no more movie tex + //----------------------------------------------------// + for(i=0;i<3;i++) // -> loop + for(j=0;j clean mem + } + for(i=0;i tex used ? + { + glDeleteTextures(1,&uiStexturePage[i]); + uiStexturePage[i]=0; // --> delete it + } + free(pxSsubtexLeft[i]); // -> clean mem + } + //----------------------------------------------------// +} + +//////////////////////////////////////////////////////////////////////// +// Reset textures in game... +//////////////////////////////////////////////////////////////////////// + +void ResetTextureArea(BOOL bDelTex) +{ + int i,j;textureSubCacheEntryS * tss;EXLong * lu; + textureWndCacheEntry * tsx; + //----------------------------------------------------// + + dwTexPageComp=0; + + //----------------------------------------------------// + if(bDelTex) {glBindTexture(GL_TEXTURE_2D,0);gTexName=0;} + //----------------------------------------------------// + tsx=wcWndtexStore; + for(i=0;iused=0; + if(bDelTex && tsx->texname) + { + glDeleteTextures(1,&tsx->texname); + tsx->texname=0; + } + } + iMaxTexWnds=0; + //----------------------------------------------------// + + for(i=0;i<3;i++) + for(j=0;jpos.l=0; + (tss+SOFFB)->pos.l=0; + (tss+SOFFC)->pos.l=0; + (tss+SOFFD)->pos.l=0; + } + + for(i=0;il=0; + if(bDelTex && uiStexturePage[i]) + {glDeleteTextures(1,&uiStexturePage[i]);uiStexturePage[i]=0;} + } +} + + +//////////////////////////////////////////////////////////////////////// +// Invalidate tex windows +//////////////////////////////////////////////////////////////////////// + +void InvalidateWndTextureArea(long X,long Y,long W, long H) +{ + int i,px1,px2,py1,py2,iYM=1; + textureWndCacheEntry * tsw=wcWndtexStore; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + + px1=max(0,(X>>6)); + px2=min(15,(W>>6)); + + if(py1==py2) + { + py1=py1<<4;px1+=py1;px2+=py1; // change to 0-31 + for(i=0;iused) + { + if(tsw->pageid>=px1 && tsw->pageid<=px2) + { + tsw->used=0; + } + } + } + } + else + { + py1=px1+16;py2=px2+16; + for(i=0;iused) + { + if((tsw->pageid>=px1 && tsw->pageid<=px2) || + (tsw->pageid>=py1 && tsw->pageid<=py2)) + { + tsw->used=0; + } + } + } + } + + // adjust tex window count + tsw=wcWndtexStore+iMaxTexWnds-1; + while(iMaxTexWnds && !tsw->used) {iMaxTexWnds--;tsw--;} +} + + + +//////////////////////////////////////////////////////////////////////// +// same for sort textures +//////////////////////////////////////////////////////////////////////// + +void MarkFree(textureSubCacheEntryS * tsx) +{ + EXLong * ul, * uls; + int j,iMax;u8 x1,y1,dx,dy; + + uls=pxSsubtexLeft[tsx->cTexID]; + iMax=uls->l;ul=uls+1; + + if(!iMax) return; + + for(j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + x1=tsx->posTX;dx=tsx->pos.c[2]-tsx->pos.c[3]; + if(tsx->posTX) {x1--;dx+=3;} + y1=tsx->posTY;dy=tsx->pos.c[0]-tsx->pos.c[1]; + if(tsx->posTY) {y1--;dy+=3;} + + ul->c[3]=x1; + ul->c[2]=dx; + ul->c[1]=y1; + ul->c[0]=dy; + } +} + +void InvalidateSubSTextureArea(long X,long Y,long W, long H) +{ + int i,j,k,iMax,px,py,px1,px2,py1,py2,iYM=1; + EXLong npos;textureSubCacheEntryS * tsb; + long x1,x2,y1,y2,xa,sw; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + px1=max(0,(X>>6)-3); + px2=min(15,(W>>6)+3); // x: 0-15 + + for(py=py1;py<=py2;py++) + { + j=(py<<4)+px1; // get page + + y1=py*256;y2=y1+255; + + if(Hy2) continue; + + if(Y>y1) y1=Y; + if(Hx2) continue; + + if(X>x1) x1=X; + if(Wpos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + +// if(npos.l & 0x00800000) + { + tsb=pscSubtexStore[k][j]+SOFFB;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00000080) + { + tsb=pscSubtexStore[k][j]+SOFFC;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00800080) + { + tsb=pscSubtexStore[k][j]+SOFFD;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// Invalidate some parts of cache: main routine +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureAreaEx(void) +{ + short W=sxmax-sxmin; + short H=symax-symin; + + if(W==0 && H==0) return; + + if(iMaxTexWnds) + InvalidateWndTextureArea(sxmin,symin,W,H); + + InvalidateSubSTextureArea(sxmin,symin,W,H); +} + +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureArea(long X,long Y,long W, long H) +{ + if(W==0 && H==0) return; + + if(iMaxTexWnds) InvalidateWndTextureArea(X,Y,W,H); + + InvalidateSubSTextureArea(X,Y,W,H); +} + + +//////////////////////////////////////////////////////////////////////// +// tex window: define +//////////////////////////////////////////////////////////////////////// + +void DefineTextureWnd(void) +{ + if(gTexName==0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, + TWin.Position.x1, + TWin.Position.y1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed stretch +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + unsigned long LineOffset;unsigned short s; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL=PTCF[DrawSemiTrans]; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load stretched +//////////////////////////////////////////////////////////////////////// + +void LoadStretchWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo,s; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + + LTCOL=TCF[DrawSemiTrans]; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + //------------------- ZN STUFF + + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + //------------------- + + start=((pageid-16*pmult)*128)+256*2048*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + //------------ ZN STUFF + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + //------------ + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed simple +//////////////////////////////////////////////////////////////////////// + +void LoadPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load simple +//////////////////////////////////////////////////////////////////////// + +void LoadWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + + LTCOL=TCF[DrawSemiTrans]; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +void UploadTexWndPal(int mode,short cx,short cy) +{ + unsigned int i,iSize; + unsigned short * wSrcPtr; + unsigned long * ta=(unsigned long *)texturepart; + + wSrcPtr=psxVuw+cx+(cy*1024); + if(mode==0) i=4; else i=64; + iSize=i<<2; + ubOpaqueDraw=0; + + do + { + *ta =PALCOL(*wSrcPtr); + *(ta+1)=PALCOL(*(wSrcPtr+1)); + *(ta+2)=PALCOL(*(wSrcPtr+2)); + *(ta+3)=PALCOL(*(wSrcPtr+3)); + ta+=4;wSrcPtr+=4;i--; + } + while(i); + +/* (*glColorTableEXTEx)(GL_TEXTURE_2D,GL_RGBA8,iSize, + GL_RGBA,GL_UNSIGNED_BYTE,texturepart); +*/} + +//////////////////////////////////////////////////////////////////////// + +void DefinePalTextureWnd(void) +{ + if(gTexName==0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, + TWin.Position.x1, + TWin.Position.y1, + 0, GL_RGBA, GL_UNSIGNED_BYTE,texturepart); +} + +/////////////////////////////////////////////////////// + +void LoadPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + u8 *ta; + u8 *cSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + + ta=(u8 *)texturepart; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2;row++) + { + *ta++=(*cSRCPtr & 0xF); row++; + if(row<=g_x2) *ta++=((*cSRCPtr >> 4) & 0xF); + cSRCPtr++; + } + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=*cSRCPtr++; + cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo; + u8 *ta,s; + u8 *cSRCPtr,*cOSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + ta=(u8 *)texturepart; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=(*cSRCPtr & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=((*cSRCPtr >> 4) & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=*cSRCPtr++; + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: main selecting, cache handler included +//////////////////////////////////////////////////////////////////////// + +GLuint LoadTextureWnd(long pageid,long TextureMode,unsigned long GivenClutId) +{ + textureWndCacheEntry * ts, * tsx=NULL; + int i;short cx,cy; + EXLong npos; + + npos.c[3]=TWin.Position.x0; + npos.c[2]=TWin.OPosition.x1; + npos.c[1]=TWin.Position.y0; + npos.c[0]=TWin.OPosition.y1; + + g_x1=TWin.Position.x0;g_x2=g_x1+TWin.Position.x1-1; + g_y1=TWin.Position.y0;g_y2=g_y1+TWin.Position.y1-1; + + if(TextureMode==2) {GivenClutId=0;cx=cy=0;} + else + { + cx=((GivenClutId << 4) & 0x3F0);cy=((GivenClutId >> 6) & CLUTYMASK); + GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30); + + // palette check sum + { + unsigned long l=0,row; + unsigned long * lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<used) + { + if(ts->pos.l==npos.l && + ts->pageid==pageid && + ts->textureMode==TextureMode) + { + if(ts->ClutID==GivenClutId) + { + ubOpaqueDraw=ts->Opaque; + return ts->texname; + } + } + } + else tsx=ts; + } + + if(!tsx) + { + if(iMaxTexWnds==iTexWndLimit) + { + tsx=wcWndtexStore+iTexWndTurn; + iTexWndTurn++; + if(iTexWndTurn==iTexWndLimit) iTexWndTurn=0; + } + else + { + tsx=wcWndtexStore+iMaxTexWnds; + iMaxTexWnds++; + } + } + + gTexName=tsx->texname; + + if(TWin.OPosition.y1==TWin.Position.y1 && + TWin.OPosition.x1==TWin.Position.x1) + { + LoadWndTexturePage(pageid,TextureMode,cx,cy); + } + else + { + LoadStretchWndTexturePage(pageid,TextureMode,cx,cy); + } + + tsx->Opaque=ubOpaqueDraw; + tsx->pos.l=npos.l; + tsx->ClutID=GivenClutId; + tsx->pageid=pageid; + tsx->textureMode=TextureMode; + tsx->texname=gTexName; + tsx->used=1; + + return gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// movie texture: define +//////////////////////////////////////////////////////////////////////// + +void DefinePackedTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0, //giWantedRGBA, + GL_RGBA, + 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, + GL_UNSIGNED_SHORT, + texturepart); +} + +//////////////////////////////////////////////////////////////////////// + +void DefineTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +#define MRED(x) ((x>>3) & 0x1f) +#define MGREEN(x) ((x>>6) & 0x3e0) +#define MBLUE(x) ((x>>9) & 0x7c00) + +#define XMGREEN(x) ((x>>5) & 0x07c0) +#define XMRED(x) ((x<<8) & 0xf800) +#define XMBLUE(x) ((x>>18) & 0x003e) + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +u8 * LoadDirectMovieFast(void) +{ + long row,column; + unsigned int startxy; + + unsigned long * ta=(unsigned long *)texturepart; + + if(PSXDisplay.RGB24) + { + u8 * pD; + + startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; + + for(column=xrMovieArea.y0;column1280 || iResY>1024) iFTex=2048; + else + if(iResX>640 || iResY>480) iFTex=1024; + else iFTex=512; + + glGenTextures(1, &gTexFrameName); + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + + p=(s8 *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iFTex, iFTex, 0, GL_RGBA, GL_UNSIGNED_BYTE, p); + free(p); + + glGetError(); + } + else + { + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + } + + x1+=PreviousPSXDisplay.Range.x0; + y1+=PreviousPSXDisplay.Range.y0; + + if(PSXDisplay.DisplayMode.x) + ScaleX=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + else ScaleX=1.0f; + if(PSXDisplay.DisplayMode.y) + ScaleY=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + else ScaleY=1.0f; + + rSrc.left =max(x1*ScaleX,0); + rSrc.right =min((x1+x2)*ScaleX+0.99f,iResX-1); + rSrc.top =max(y1*ScaleY,0); + rSrc.bottom=min((y1+y2)*ScaleY+0.99f,iResY-1); + + iYAdjust=(y1+y2)-PSXDisplay.DisplayMode.y; + if(iYAdjust>0) + iYAdjust=(int)((float)iYAdjust*ScaleY)+1; + else iYAdjust=0; + + gl_vy[0]=255-gl_vy[0]; + gl_vy[1]=255-gl_vy[1]; + gl_vy[2]=255-gl_vy[2]; + gl_vy[3]=255-gl_vy[3]; + + y1=min(gl_vy[0],min(gl_vy[1],min(gl_vy[2],gl_vy[3]))); + + gl_vy[0]-=y1; + gl_vy[1]-=y1; + gl_vy[2]-=y1; + gl_vy[3]-=y1; + gl_ux[0]-=gl_ux[7]; + gl_ux[1]-=gl_ux[7]; + gl_ux[2]-=gl_ux[7]; + gl_ux[3]-=gl_ux[7]; + + ScaleX*=256.0f/((float)(iFTex)); + ScaleY*=256.0f/((float)(iFTex)); + + y1=((float)gl_vy[0]*ScaleY); if(y1>255) y1=255; + gl_vy[0]=y1; + y1=((float)gl_vy[1]*ScaleY); if(y1>255) y1=255; + gl_vy[1]=y1; + y1=((float)gl_vy[2]*ScaleY); if(y1>255) y1=255; + gl_vy[2]=y1; + y1=((float)gl_vy[3]*ScaleY); if(y1>255) y1=255; + gl_vy[3]=y1; + + x1=((float)gl_ux[0]*ScaleX); if(x1>255) x1=255; + gl_ux[0]=x1; + x1=((float)gl_ux[1]*ScaleX); if(x1>255) x1=255; + gl_ux[1]=x1; + x1=((float)gl_ux[2]*ScaleX); if(x1>255) x1=255; + gl_ux[2]=x1; + x1=((float)gl_ux[3]*ScaleX); if(x1>255) x1=255; + gl_ux[3]=x1; + + x1=rSrc.right-rSrc.left; + if(x1<=0) x1=1; + if(x1>iFTex) x1=iFTex; + + y1=rSrc.bottom-rSrc.top; + if(y1<=0) y1=1; + if(y1+iYAdjust>iFTex) y1=iFTex-iYAdjust; + + + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, + 0, + iYAdjust, + rSrc.left+rRatioRect.left, + iResY-rSrc.bottom-rRatioRect.top, + x1,y1); + + if(glGetError()) + { + s8 * p=(s8 *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iFTex, iFTex, + GL_RGBA, GL_UNSIGNED_BYTE, p); + free(p); + } + + + ubOpaqueDraw=0; + + if(iSpriteTex) + { + sprtW=gl_ux[1]-gl_ux[0]; + sprtH=-(gl_vy[0]-gl_vy[2]); + } + + return (GLuint)gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (unpacked) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + unsigned long x2a,xalign=0; + unsigned long x1=gl_ux[7]; + unsigned long x2=gl_ux[6]; + unsigned long y1=gl_ux[5]; + unsigned long y2=gl_ux[4]; + unsigned long dx=x2-x1+1; + unsigned long dy=y2-y1+1; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + unsigned int a,r,g,b,cnt,h; + unsigned long scol[8]; + + LTCOL=TCF[DrawSemiTrans]; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*wSRCPtr++);row--;} while(row); + ta+=xalign; + wSRCPtr+=LineOffset;column--; + } + while(column); + + break; + //--------------------------------------------------// + // others are not possible ! + } + + x2a=dx+xalign; + + if(YTexS) + { + ta=(unsigned long *)texturepart; + pa=(unsigned long *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + pa=(unsigned long *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(unsigned long *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + pa=(unsigned long *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(unsigned long *)texturepart; + x1=dx-1; + y1=dy-1; + + if(bOpaquePass) + { +{ + for(column=0;column>24!=1) scol[cnt++]=*(ta-dx); + if(row && *(ta-1) !=0x50000000 && *(ta-1)>>24!=1) scol[cnt++]=*(ta-1); + if(row!=x1 && *(ta+1) !=0x50000000 && *(ta+1)>>24!=1) scol[cnt++]=*(ta+1); + if( column!=y1 && *(ta+dx) !=0x50000000 && *(ta+dx)>>24!=1) scol[cnt++]=*(ta+dx); + + if(row && column && *(ta-dx-1)!=0x50000000 && *(ta-dx-1)>>24!=1) scol[cnt++]=*(ta-dx-1); + if(row!=x1 && column && *(ta-dx+1)!=0x50000000 && *(ta-dx+1)>>24!=1) scol[cnt++]=*(ta-dx+1); + if(row && column!=y1 && *(ta+dx-1)!=0x50000000 && *(ta+dx-1)>>24!=1) scol[cnt++]=*(ta+dx-1); + if(row!=x1 && column!=y1 && *(ta+dx+1)!=0x50000000 && *(ta+dx+1)>>24!=1) scol[cnt++]=*(ta+dx+1); + + if(cnt) + { + r=g=b=a=0; + for(h=0;h>24); + r+=(scol[h]>>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + + *ta=(r<<16)|(g<<8)|b; + if(a) *ta|=0x50000000; + else *ta|=0x01000000; + } + } + ta++; + } + } + } + } + else + for(column=0;column>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<16)|(g<<8)|b; + } + } + ta++; + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (packed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + unsigned long x2a,xalign=0; + unsigned long x1=gl_ux[7]; + unsigned long x2=gl_ux[6]; + unsigned long y1=gl_ux[5]; + unsigned long y2=gl_ux[4]; + unsigned long dx=x2-x1+1; + unsigned long dy=y2-y1+1; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + unsigned int a,r,g,b,cnt,h; + unsigned short scol[8]; + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF));row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) // more pix? use lut + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else // small area? no lut + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*wSRCPtr++);row--;} while(row); + + ta+=xalign; + + wSRCPtr+=LineOffset;column--; + } + while(column); + break; + //--------------------------------------------------// + // others are not possible ! + } + + //////////////////////////////////////////////////////// + + x2a=dx+xalign; + + if(YTexS) + { + ta=(unsigned short *)texturepart; + pa=(unsigned short *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + pa=(unsigned short *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(unsigned short *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + pa=(unsigned short *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(unsigned short *)texturepart; + x1=dx-1; + y1=dy-1; + +{ + for(column=0;column>11; + g+=(scol[h]>>6)&0x1f; + b+=(scol[h]>>1)&0x1f; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<11)|(g<<6)|(b<<1); + } + } + ta++; + } + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// hires texture funcs +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +//////////////////////////////////////////////////////////////////////// + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + + +#define INTERPOLATE8_02(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8_02(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((C&0xFF000000)==0x03000000)?0x03000000:(((D&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +#define INTERPOLATE8(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((C&0xFF000000)==0x50000000)?0x50000000:(((D&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +void Super2xSaI_ex8_Ex(u8 *srcPtr, DWORD srcPitch, + u8 *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8_02(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8_02 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8_02 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8_02 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8_02 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8_02 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8_02 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8_02(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8_02(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8_02(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8_02(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + + +void Super2xSaI_ex8(u8 *srcPtr, DWORD srcPitch, + u8 *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} +///////////////////////////////////////////////////////////////////////////// + +#define colorMask4 0x0000EEE0 +#define lowPixelMask4 0x00001110 +#define qcolorMask4 0x0000CCC0 +#define qlowpixelMask4 0x00003330 + +#define INTERPOLATE4(A, B) ((((A & colorMask4) >> 1) + ((B & colorMask4) >> 1) + (A & B & lowPixelMask4))|((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))) + +#define Q_INTERPOLATE4(A, B, C, D) ((((A & qcolorMask4) >> 2) + ((B & qcolorMask4) >> 2) + ((C & qcolorMask4) >> 2) + ((D & qcolorMask4) >> 2) + ((((A & qlowpixelMask4) + (B & qlowpixelMask4) + (C & qlowpixelMask4) + (D & qlowpixelMask4)) >> 2) & qlowpixelMask4))| ((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((C&0x0000000F)==0x00000006)?0x00000006:(((D&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:(((C&0x0000000F)==0x00000000)?0x00000000:(((D&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))))))) + + +#define colorMask5 0x0000F7BC +#define lowPixelMask5 0x00000842 +#define qcolorMask5 0x0000E738 +#define qlowpixelMask5 0x000018C6 + +#define INTERPOLATE5(A, B) ((((A & colorMask5) >> 1) + ((B & colorMask5) >> 1) + (A & B & lowPixelMask5))|((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:0x00000001)))) + +#define Q_INTERPOLATE5(A, B, C, D) ((((A & qcolorMask5) >> 2) + ((B & qcolorMask5) >> 2) + ((C & qcolorMask5) >> 2) + ((D & qcolorMask5) >> 2) + ((((A & qlowpixelMask5) + (B & qlowpixelMask5) + (C & qlowpixelMask5) + (D & qlowpixelMask5)) >> 2) & qlowpixelMask5))| ((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:(((C&0x00000001)==0x00000000)?0x00000000:(((D&0x00000001)==0x00000000)?0x00000000:0x00000001)))))) +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// ogl texture defines +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void DefineSubTextureSortHiRes(void) +{ + int x,y,dx2; + + if(!gTexName) + { + glGenTextures(1, &gTexName); + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(iFilterType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturebuffer); + } + else glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexSubImage2D(GL_TEXTURE_2D, 0, XTexS<<1, YTexS<<1, + DXTexS<<1, DYTexS<<1, + GL_RGBA, GL_UNSIGNED_BYTE, texturebuffer); +} + +///////////////////////////////////////////////////////////////////////////// + +void DefineSubTextureSort(void) +{ + + if(!gTexName) + { + glGenTextures(1, &gTexName); + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(iFilterType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexSubImage2D(GL_TEXTURE_2D, 0, XTexS, YTexS, + DXTexS, DYTexS, + GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// texture cache garbage collection +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void DoTexGarbageCollection(void) +{ + static unsigned short LRUCleaned=0; + unsigned short iC,iC1,iC2; + int i,j,iMax;textureSubCacheEntryS * tsb; + + iC=4;//=iSortTexCnt/2, + LRUCleaned+=iC; // we clean different textures each time + if((LRUCleaned+iC)>=iSortTexCnt) LRUCleaned=0; // wrap? wrap! + iC1=LRUCleaned; // range of textures to clean + iC2=LRUCleaned+iC; + + for(iC=iC1;iCl=0; + } + + for(i=0;i<3;i++) // remove all references to that textures + for(j=0;jpos.l; + if(iMax) + do + { + tsb++; + if(tsb->cTexID>=iC1 && tsb->cTexIDClutID=0; + } + while(--iMax); + } + + usLRUTexPage=LRUCleaned; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for existing (already used) parts +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +u8 * CheckTextureInSubSCache(long TextureMode,unsigned long GivenClutId,unsigned short * pCache) +{ + textureSubCacheEntryS * tsx, * tsb, *tsg;//, *tse=NULL; + int i,iMax;EXLong npos; + u8 cx,cy; + int iC,j,k;unsigned long rx,ry,mx,my; + EXLong * ul=0, * uls; + EXLong rfree; + u8 cXAdj,cYAdj; + + npos.l=*((unsigned long *)&gl_ux[4]); + + //--------------------------------------------------------------// + // find matching texturepart first... speed up... + //--------------------------------------------------------------// + + tsg=pscSubtexStore[TextureMode][GlobalTexturePage]; + tsg+=((GivenClutId&CLUTCHK)>>CLUTSHIFT)*SOFFB; + + iMax=tsg->pos.l; + if(iMax) + { + i=iMax; + tsb=tsg+1; + do + { + if(GivenClutId==tsb->ClutID && + (INCHECK(tsb->pos,npos))) + { + { + cx=tsb->pos.c[3]-tsb->posTX; + cy=tsb->pos.c[1]-tsb->posTY; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + ubOpaqueDraw=tsb->Opaque; + *pCache=tsb->cTexID; + return NULL; + } + } + tsb++; + } + while(--i); + } + + //----------------------------------------------------// + + cXAdj=1;cYAdj=1; + + rx=(int)gl_ux[6]-(int)gl_ux[7]; + ry=(int)gl_ux[4]-(int)gl_ux[5]; + + tsx=NULL;tsb=tsg+1; + for(i=0;iClutID) {tsx=tsb;break;} + } + + if(!tsx) + { + iMax++; + if(iMax>=SOFFB-2) + { + if(iTexGarbageCollection) // gc mode? + { + if(*pCache==0) + { + dwTexPageComp|=(1<ClutID) + { + if(!tsx) {tsx=tsb;rfree.l=npos.l;} // + else tsb->ClutID=0; + rfree.c[3]=min(rfree.c[3],tsb->pos.c[3]); + rfree.c[2]=max(rfree.c[2],tsb->pos.c[2]); + rfree.c[1]=min(rfree.c[1],tsb->pos.c[1]); + rfree.c[0]=max(rfree.c[0],tsb->pos.c[0]); + MarkFree(tsb); + } + + if(tsx) // 3. if one or more found, create a new rect with bigger size + { + *((unsigned long *)&gl_ux[4])=npos.l=rfree.l; + rx=(int)rfree.c[2]-(int)rfree.c[3]; + ry=(int)rfree.c[0]-(int)rfree.c[1]; + DoTexGarbageCollection(); + + goto ENDLOOP3; + } + } + + iMax=1; + } + tsx=tsg+iMax; + tsg->pos.l=iMax; + } + + //----------------------------------------------------// + // now get a free texture space + //----------------------------------------------------// + + if(iTexGarbageCollection) usLRUTexPage=0; + +ENDLOOP3: + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto ENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto ENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto ENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +ENDLOOP: + if(ul) + { + ////////////////////////////////////////////////////// + + { + dwTexPageComp=0; + + for(i=0;i<3;i++) // cleaning up + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + } + + ////////////////////////////////////////////////////// + iC=usLRUTexPage; + uls=pxSsubtexLeft[usLRUTexPage]; + uls->l=0;ul=uls+1; + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;} + else + { + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + } + tsg->pos.l=1;tsx=tsg+1; + } + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID =*pCache=iC; + tsx->pos = npos; + tsx->ClutID = GivenClutId; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + cx=gl_ux[7]-rfree.c[3]; + cy=gl_ux[5]-rfree.c[1]; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return &tsx->Opaque; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for free place (on compress) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +BOOL GetCompressTexturePlace(textureSubCacheEntryS * tsx) +{ + int i,j,k,iMax,iC;unsigned long rx,ry,mx,my; + EXLong * ul=0, * uls, rfree; + u8 cXAdj=1,cYAdj=1; + + rx=(int)tsx->pos.c[2]-(int)tsx->pos.c[3]; + ry=(int)tsx->pos.c[0]-(int)tsx->pos.c[1]; + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto TENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto TENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto TENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +TENDLOOP: + if(ul) return FALSE; + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID = iC; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// compress texture cache (to make place for new texture part, if needed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void CompressTextureSpace(void) +{ + textureSubCacheEntryS * tsx, * tsg, * tsb; + int i,j,k,m,n,iMax;EXLong * ul, r,opos; + short sOldDST=DrawSemiTrans,cx,cy; + long lOGTP=GlobalTexturePage; + unsigned long l,row; + unsigned long * lSRCPtr; + + opos.l=*((unsigned long *)&gl_ux[4]); + + // 1. mark all textures as free + for(i=0;il=0;} + usLRUTexPage=0; + + // 2. compress + for(j=0;j<3;j++) + { + for(k=0;kpos.l=0; + (tsg+SOFFB)->pos.l=0; + (tsg+SOFFC)->pos.l=0; + (tsg+SOFFD)->pos.l=0; + continue; + } + + for(m=0;m<4;m++,tsg+=SOFFB) + { + iMax=tsg->pos.l; + + tsx=tsg+1; + for(i=0;iClutID) + { + r.l=tsx->pos.l; + for(n=i+1,tsb=tsx+1;nClutID==tsb->ClutID) + { + r.c[3]=min(r.c[3],tsb->pos.c[3]); + r.c[2]=max(r.c[2],tsb->pos.c[2]); + r.c[1]=min(r.c[1],tsb->pos.c[1]); + r.c[0]=max(r.c[0],tsb->pos.c[0]); + tsb->ClutID=0; + } + } + +// if(r.l!=tsx->pos.l) + { + cx=((tsx->ClutID << 4) & 0x3F0); + cy=((tsx->ClutID >> 6) & CLUTYMASK); + + if(j!=2) + { + // palette check sum + l=0;lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(j==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<ClutID&(0x00003fff<<16))) + { + tsx->ClutID=0;continue; + } + } + + tsx->pos.l=r.l; + if(!GetCompressTexturePlace(tsx)) // no place? + { + for(i=0;i<3;i++) // -> clean up everything + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + DrawSemiTrans=sOldDST; + GlobalTexturePage=lOGTP; + *((unsigned long *)&gl_ux[4])=opos.l; + dwTexPageComp=0; + + return; + } + + if(tsx->ClutID&(1<<30)) DrawSemiTrans=1; + else DrawSemiTrans=0; + *((unsigned long *)&gl_ux[4])=r.l; + + gTexName=uiStexturePage[tsx->cTexID]; + LoadSubTexFn(k,j,cx,cy); + uiStexturePage[tsx->cTexID]=gTexName; + tsx->Opaque=ubOpaqueDraw; + } + } + } + + if(iMax) + { + tsx=tsg+iMax; + while(!tsx->ClutID && iMax) {tsx--;iMax--;} + tsg->pos.l=iMax; + } + + } + } + } + + if(dwTexPageComp==0xffffffff) dwTexPageComp=0; + + *((unsigned long *)&gl_ux[4])=opos.l; + GlobalTexturePage=lOGTP; + DrawSemiTrans=sOldDST; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// main entry for searching/creating textures, called from prim.c +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +GLuint SelectSubTextureS(long TextureMode, unsigned long GivenClutId) +{ + u8 * OPtr;unsigned short iCache;short cx,cy; + + // sort sow/tow infos for fast access + + u8 ma1,ma2,mi1,mi2; + if(gl_ux[0]>gl_ux[1]) {mi1=gl_ux[1];ma1=gl_ux[0];} + else {mi1=gl_ux[0];ma1=gl_ux[1];} + if(gl_ux[2]>gl_ux[3]) {mi2=gl_ux[3];ma2=gl_ux[2];} + else {mi2=gl_ux[2];ma2=gl_ux[3];} + if(mi1>mi2) gl_ux[7]=mi2; + else gl_ux[7]=mi1; + if(ma1>ma2) gl_ux[6]=ma1; + else gl_ux[6]=ma2; + + if(gl_vy[0]>gl_vy[1]) {mi1=gl_vy[1];ma1=gl_vy[0];} + else {mi1=gl_vy[0];ma1=gl_vy[1];} + if(gl_vy[2]>gl_vy[3]) {mi2=gl_vy[3];ma2=gl_vy[2];} + else {mi2=gl_vy[2];ma2=gl_vy[3];} + if(mi1>mi2) gl_ux[5]=mi2; + else gl_ux[5]=mi1; + if(ma1>ma2) gl_ux[4]=ma1; + else gl_ux[4]=ma2; + + // get clut infos in one 32 bit val + + if(TextureMode==2) // no clut here + { + GivenClutId=CLUTUSED|(DrawSemiTrans<<30);cx=cy=0; + + if(iFrameTexType && Fake15BitTexture()) + return (GLuint)gTexName; + } + else + { + cx=((GivenClutId << 4) & 0x3F0); // but here + cy=((GivenClutId >> 6) & CLUTYMASK); + GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30)|CLUTUSED; + + // palette check sum.. removed MMX asm, this easy func works as well + { + unsigned long l=0,row; + + unsigned long * lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)< Date: Fri, 31 Dec 2010 17:25:34 +0200 Subject: [PATCH 15/16] Pickle's port for this emu --- plugins/gpu-gles/Makefile | 43 ++++++ plugins/gpu-gles/gpuDraw.c | 229 +++++++++++++++++++++++++------- plugins/gpu-gles/gpuDraw.h | 3 +- plugins/gpu-gles/gpuExternals.h | 21 +-- plugins/gpu-gles/gpuPlugin.c | 71 +++++----- plugins/gpu-gles/gpuPlugin.h | 56 ++++---- plugins/gpu-gles/gpuPrim.c | 8 +- plugins/gpu-gles/gpuStdafx.h | 16 ++- plugins/gpu-gles/gpuTexture.c | 21 +-- 9 files changed, 317 insertions(+), 151 deletions(-) create mode 100644 plugins/gpu-gles/Makefile diff --git a/plugins/gpu-gles/Makefile b/plugins/gpu-gles/Makefile new file mode 100644 index 00000000..48f84b89 --- /dev/null +++ b/plugins/gpu-gles/Makefile @@ -0,0 +1,43 @@ +############################################################################## +# MAKEFILE FOR PETE'S MESAGL GPU... just run "make" +############################################################################## + +############################################################################## +# 1. SETS (CCFLAGS3 is used) +############################################################################## + +PREFIX = /mythtv/media/devel/toolchains/pandora/arm-2007q3 +TARGET = arm-none-linux-gnueabi- + +CC = $(PREFIX)/bin/$(TARGET)gcc + +CCFLAGS = -fPIC -c -Wall -O3 -ffast-math -fomit-frame-pointer -DMAEMO_CHANGES -DUSE_X11 + + +INCLUDE = -I$(PREFIX)/include +LINK = $(PREFIX)/bin/$(TARGET)gcc +LINKFLAGS = -shared -Wl,-soname,libgpuGLES.so -o libgpuGLES.so.1.0.0 +OBJ = gpuDraw.o gpuFps.o gpuPlugin.o gpuPrim.o gpuTexture.o + +LIB = -L$(PREFIX)/lib -lGLES_CM -lX11 -lXau -lXdmcp -lstdc++ + +############################################################################## +# 2. MAIN RULE +############################################################################## + +gpuPeopsMesaGL : $(OBJ) + $(LINK) $(LINKFLAGS) $(OBJ) $(LIB) + +############################################################################## +# 3. GENERAL RULES +############################################################################## + +%.o : %.c + $(CC) $(CCFLAGS) $(INCLUDE) $< + +############################################################################## +# 4. SPECIFIC RULES +############################################################################## + +clean: + rm *.o libgpuGLES.so* \ No newline at end of file diff --git a/plugins/gpu-gles/gpuDraw.c b/plugins/gpu-gles/gpuDraw.c index 3d09c333..597f286b 100644 --- a/plugins/gpu-gles/gpuDraw.c +++ b/plugins/gpu-gles/gpuDraw.c @@ -39,7 +39,7 @@ #include "texture.h" #else #include "gpuExternals.h" -#include "GPUPlugin.h" +#include "gpuPlugin.h" #include "gpuDraw.h" #include "gpuPrim.h" #include "gpuTexture.h" @@ -309,6 +309,48 @@ HGLRC GLCONTEXT=NULL; #endif #ifdef MAEMO_CHANGES +#define MODE_RAW 0 +#define MODE_X11 1 +#define MODE_SDL 2 +int pandora_driver_mode = MODE_RAW; +int use_fsaa = 0; + +EGLDisplay display; +EGLConfig config; +EGLContext context; +EGLSurface surface; + +#if defined(USE_X11) +#include "X11/Xlib.h" +#include "X11/Xutil.h" +#include "X11/Xatom.h" + +Window x11Window = 0; +Display* x11Display = 0; +long x11Screen = 0; +XVisualInfo x11Visual; +XVisualInfo* px11Visual = 0; +Colormap x11Colormap = 0; +#endif + +EGLint attrib_list_fsaa[] = +{ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BUFFER_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_SAMPLE_BUFFERS, 1, + EGL_SAMPLES, 4, + EGL_NONE +}; + +EGLint attrib_list[] = +{ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BUFFER_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_NONE +}; + bool TestEGLError(const char* pszLocation) { /* @@ -320,79 +362,154 @@ bool TestEGLError(const char* pszLocation) if (iErr != EGL_SUCCESS) { printf("%s failed (%d).\n", pszLocation, iErr); - return false; + return FALSE; } - return true; + return TRUE; } void maemoGLinit(){ - iResX= 800; - iResY =480; + printf ("GL init\n"); + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; +#if defined(USE_X11) + enum + { + _NET_WM_STATE_REMOVE =0, + _NET_WM_STATE_ADD = 1, + _NET_WM_STATE_TOGGLE =2 + }; - printf ("maemo GL init\n"); - long int winxid=GDK_WINDOW_XID(GTK_WIDGET(windowG)->window); - printf ("%d\n",winxid); + Window sRootWindow; + XSetWindowAttributes sWA; + unsigned int ui32Mask; + int i32Depth; +#endif - EGLContext context = 0; - EGLConfig eglConfig = 0; - EGLContext eglContext = 0; - display = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + EGLint *attribList = NULL; + if (use_fsaa) + { + printf( "GLES: Using Full Scene Antialiasing\n" ); + attribList = attrib_list_fsaa; + } + else + { + attribList = attrib_list; + } + +#if defined(USE_X11) + pandora_driver_mode = MODE_X11; // TODO make configurable +#else + pandora_driver_mode = MODE_RAW; // TODO make configurable +#endif - if( eglInitialize( display, NULL, NULL ) == EGL_FALSE ) + switch(pandora_driver_mode) { - printf( "EGL Initialize failed!\n" ); +#if defined(USE_X11) + case MODE_X11: + // Initializes the display and screen + x11Display = XOpenDisplay( ":0" ); + if (!x11Display) + { + printf("GLES Error: Unable to open X display\n"); + } + x11Screen = XDefaultScreen( x11Display ); + // Gets the display parameters so we can pass the same parameters to the window to be created. + sRootWindow = RootWindow(x11Display, x11Screen); + i32Depth = DefaultDepth(x11Display, x11Screen); + px11Visual = &x11Visual; + XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, px11Visual); + if (!px11Visual) + { + printf("GLES Error: Unable to acquire visual\n"); } + // Colormap of the specified visual type for the display. + x11Colormap = XCreateColormap( x11Display, sRootWindow, px11Visual->visual, AllocNone ); + sWA.colormap = x11Colormap; + + // List of events to be handled by the application. Add to these for handling other events. + sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; -const EGLint attributeList[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - /*EGL_BUFFER_SIZE, 32, */ - EGL_NONE - }; + // Display capabilities list. + ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; - EGLint pi32ConfigAttribs[5]; - pi32ConfigAttribs[0] = EGL_SURFACE_TYPE; - pi32ConfigAttribs[1] = EGL_WINDOW_BIT; - pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE; - pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT; - pi32ConfigAttribs[4] = EGL_NONE; - - EGLint pi32ContextAttribs[3]; - pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION; - pi32ContextAttribs[1] = 2; - pi32ContextAttribs[2] = EGL_NONE; - - int iConfigs; - if (!eglChooseConfig(display, attributeList, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) + // Creates the X11 window + x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, iResX, iResY, + 0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA); + + // Make the window viewable and flush the output buffer. + XMapWindow(x11Display, x11Window); + XFlush(x11Display); + + // Make the window fullscreen + unsigned char fullScreen = 1; + Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False); + Atom wmFullScreen = XInternAtom(x11Display,"_NET_WM_STATE_FULLSCREEN", False); + + XEvent xev; + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.window = x11Window; + xev.xclient.message_type = wmState; + xev.xclient.format = 32; + xev.xclient.data.l[0] = (fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); + xev.xclient.data.l[1] = wmFullScreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(x11Display, DefaultRootWindow(x11Display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + display = eglGetDisplay( (EGLNativeDisplayType)x11Display ); + break; +#endif + case MODE_RAW: + default: + display = eglGetDisplay( (EGLNativeDisplayType)0 ); + break; + } + + if( display == EGL_NO_DISPLAY ) { - printf("Error: eglChooseConfig() failed.\n"); + printf( "GLES EGL Error: GL No Display\n" ); } - printf ("%d\n",iConfigs); - surface = eglCreateWindowSurface(display, eglConfig, (void*)winxid, NULL); - printf ("%d\n",surface); - if (!TestEGLError("eglCreateWindowSurface")) + + if( !eglInitialize( display, &majorVersion, &minorVersion ) ) { - printf ("eglCreateWindowSurface fail"); + printf( "GLES EGL Error: eglInitialize failed\n" ); } - //context = eglCreateContext(display, eglConfig, NULL, pi32ContextAttribs); - context =eglCreateContext( display, eglConfig, - EGL_NO_CONTEXT, NULL - ); -printf ("%d\n",context); - if (!TestEGLError("eglCreateContext")) + if( !eglChooseConfig( display, attribList, &config, 1, &numConfigs ) ) { - printf("error eglCreateContext"); + printf( "GLES EGL Error: eglChooseConfig failed\n" ); } - eglMakeCurrent(display, surface, surface, context); + context = eglCreateContext( display, config, NULL, NULL ); + if( context==0 ) + { + printf( "GLES EGL Error: eglCreateContext failed\n" ); + } - if (!TestEGLError("eglMakeCurrent")) + switch(pandora_driver_mode) { - printf("error eglMakeCurrent"); +#if defined(USE_X11) + case MODE_X11: + surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)x11Window, NULL ); + break; +#endif + case MODE_RAW: + default: + surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)0, NULL ); + break; } + + eglMakeCurrent( display, surface, surface, context ); + if (!TestEGLError("eglMakeCurrent")) + printf("error eglMakeCurrent"); + else + printf("GLES Window Opened\n"); } #endif @@ -505,6 +622,20 @@ void GLcleanup() if(!bWindowMode && dcGlobal) ReleaseDC(hWWindow,dcGlobal); #endif + + eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); + eglDestroySurface( display, surface ); + eglDestroyContext( display, context ); + eglTerminate( display ); + +#if defined(USE_X11) + if (pandora_driver_mode == MODE_X11) + { + if (x11Window) XDestroyWindow(x11Display, x11Window); + if (x11Colormap) XFreeColormap( x11Display, x11Colormap ); + if (x11Display) XCloseDisplay(x11Display); + } +#endif } //////////////////////////////////////////////////////////////////////// diff --git a/plugins/gpu-gles/gpuDraw.h b/plugins/gpu-gles/gpuDraw.h index f5f0426a..c59927d7 100644 --- a/plugins/gpu-gles/gpuDraw.h +++ b/plugins/gpu-gles/gpuDraw.h @@ -33,8 +33,7 @@ extern "C" { #endif -#include "minimal.h" -#include + // internally used defines diff --git a/plugins/gpu-gles/gpuExternals.h b/plugins/gpu-gles/gpuExternals.h index f24c31ad..977d74d4 100644 --- a/plugins/gpu-gles/gpuExternals.h +++ b/plugins/gpu-gles/gpuExternals.h @@ -32,7 +32,16 @@ #ifdef __cplusplus extern "C" { #endif -#define _GPU_API_ + +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short int u16; +typedef signed short int s16; +typedef unsigned long u32; +typedef signed long s32; +typedef unsigned long long int u64; +typedef signed long long int s64; + #ifndef _WINDOWS #ifdef __NANOGL__ #include @@ -41,19 +50,13 @@ extern "C" { #ifdef SOFT_LINKAGE #pragma softfp_linkage #endif -#include // for opengl es types +#include // for opengl es types #ifdef SOFT_LINKAGE #pragma no_softfp_linkage #endif #endif #endif -#ifdef MAEMO_CHANGES - #include "../psxCommon.h" -#else - #include "psxCommon.h" -#endif - #ifdef __NANOGL__ #define glTexParameteri(x,y,z) glTexParameterf(x,y,z) #define glAlphaFuncx(x,y) glAlphaFunc(x,y) @@ -529,7 +532,7 @@ typedef struct { int x; int y; } Vec2f; -/**/ +*/ typedef struct { Vec3f xyz; diff --git a/plugins/gpu-gles/gpuPlugin.c b/plugins/gpu-gles/gpuPlugin.c index 07f158c3..d6e6fbb2 100644 --- a/plugins/gpu-gles/gpuPlugin.c +++ b/plugins/gpu-gles/gpuPlugin.c @@ -396,7 +396,7 @@ void DoSnapShot(void) #ifdef _WINDOWS void CALLBACK GPUmakeSnapshot(void) #else -void CALLBACK GPU_makeSnapshot(void) +void CALLBACK GPUmakeSnapshot(void) #endif { //bSnapShot = TRUE; @@ -409,7 +409,7 @@ void CALLBACK GPU_makeSnapshot(void) #ifdef _WINDOWS long CALLBACK GPUinit() #else -long CALLBACK GPU_init() +long CALLBACK GPUinit() #endif { memset(ulStatusControl,0,256*sizeof(unsigned long)); @@ -543,7 +543,7 @@ HMENU hPSEMenu=NULL; long CALLBACK GPUopen(HWND hwndGPU) #else -long CALLBACK GPU_open(int hwndGPU) +long CALLBACK GPUopen(int hwndGPU) #endif { #ifdef _WINDOWS @@ -555,12 +555,13 @@ long CALLBACK GPU_open(int hwndGPU) - - #ifdef _WINDOWS iResX=240;iResY=320; #endif - iColDepth=32; +#ifdef MAEMO_CHANGES + iResX=640;iResY=480; +#endif + iColDepth=8; bChangeRes=FALSE; #ifdef _WINDOWS bWindowMode=TRUE; @@ -705,7 +706,7 @@ long CALLBACK GPUclose() // WINDOWS CLOSE #else -long GPU_close() // LINUX CLOSE +long GPUclose() // LINUX CLOSE { GLcleanup(); // close OGL @@ -725,7 +726,7 @@ long GPU_close() // LINUX CLOSE #ifdef _WINDOWS long CALLBACK GPUshutdown() #else -long CALLBACK GPU_shutdown() +long CALLBACK GPUshutdown() #endif { if(psxVSecure) free(psxVSecure); // kill emulated vram memory @@ -783,7 +784,7 @@ void SetScanLines(void) int iLastRGB24=0; // special vars for checking when to skip two display updates int iSkipTwo=0; -void GPU_vSinc(void){ +void GPUvSinc(void){ updateDisplay(); } void updateDisplay(void) // UPDATE DISPLAY @@ -1314,7 +1315,7 @@ static unsigned short usFirstPos=2; #ifdef _WINDOWS void CALLBACK GPUupdateLace(void) #else -void CALLBACK GPU_updateLace(void) +void CALLBACK GPUupdateLace(void) #endif { if(!(dwActFixes&0x1000)) @@ -1356,7 +1357,7 @@ if(bChangeWinMode) ChangeWindowMode(); #ifdef _WINDOWS unsigned long CALLBACK GPUreadStatus(void) #else -unsigned long CALLBACK GPU_readStatus(void) +unsigned long CALLBACK GPUreadStatus(void) #endif { if(dwActFixes&0x1000) // CC game fix @@ -1396,7 +1397,7 @@ return STATUSREG; #ifdef _WINDOWS void CALLBACK GPUwriteStatus(unsigned long gdata) #else -void CALLBACK GPU_writeStatus(unsigned long gdata) +void CALLBACK GPUwriteStatus(unsigned long gdata) #endif { unsigned long lCommand=(gdata>>24)&0xff; @@ -2012,7 +2013,7 @@ void CheckVRamRead(int x, int y, int dx, int dy, bool bFront) #ifdef _WINDOWS void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize) #else -void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize) +void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize) #endif { int i; @@ -2088,14 +2089,14 @@ GPUIsIdle; #ifdef _WINDOWS unsigned long CALLBACK GPUreadData(void) #else -unsigned long CALLBACK GPU_readData(void) +unsigned long CALLBACK GPUreadData(void) #endif { unsigned long l; #ifdef _WINDOWS GPUreadDataMem(&l,1); #else - GPU_readDataMem(&l,1); + GPUreadDataMem(&l,1); #endif return GPUdataRet; } @@ -2181,7 +2182,7 @@ const u8 primTableCX[256] = #ifdef _WINDOWS void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize) #else -void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize) +void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize) #endif { u8 command; @@ -2304,13 +2305,13 @@ GPUIsIdle; #ifdef _WINDOWS void CALLBACK GPUwriteData(unsigned long gdata) #else -void CALLBACK GPU_writeData(unsigned long gdata) +void CALLBACK GPUwriteData(unsigned long gdata) #endif { #ifdef _WINDOWS GPUwriteDataMem(&gdata,1); #else - GPU_writeDataMem(&gdata,1); + GPUwriteDataMem(&gdata,1); #endif } @@ -2398,7 +2399,7 @@ void StartCfgTool(s8 * pCmdLine) // linux: start external cf #ifdef _WINDOWS long CALLBACK GPUconfigure(void) #else -long CALLBACK GPU_configure(void) +long CALLBACK GPUconfigure(void) #endif { @@ -2452,7 +2453,7 @@ return FALSE; #ifdef _WINDOWS long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr) #else -long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr) +long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr) #endif { unsigned long dmaMem; @@ -2481,7 +2482,7 @@ do #ifdef _WINDOWS if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); #else - if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count); + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); #endif addr = baseAddrL[addr>>2]&0xffffff; @@ -2500,7 +2501,7 @@ return 0; #ifdef _WINDOWS void CALLBACK GPUabout(void) #else -void CALLBACK GPU_about(void) +void CALLBACK GPUabout(void) #endif { @@ -2513,7 +2514,7 @@ void CALLBACK GPU_about(void) #ifdef _WINDOWS long CALLBACK GPUtest(void) #else -long CALLBACK GPU_test(void) +long CALLBACK GPUtest(void) #endif { // if test fails this function should return negative value for error (unable to continue) @@ -2531,7 +2532,7 @@ long CALLBACK GPU_test(void) #ifdef _WINDOWS long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) #else -long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) #endif { if(ulGetFreezeData==2) @@ -2574,15 +2575,15 @@ ResetTextureArea(TRUE); GPUwriteStatus(ulStatusControl[5]); GPUwriteStatus(ulStatusControl[4]); #else - GPU_writeStatus(ulStatusControl[0]); - GPU_writeStatus(ulStatusControl[1]); - GPU_writeStatus(ulStatusControl[2]); - GPU_writeStatus(ulStatusControl[3]); - GPU_writeStatus(ulStatusControl[8]); - GPU_writeStatus(ulStatusControl[6]); - GPU_writeStatus(ulStatusControl[7]); - GPU_writeStatus(ulStatusControl[5]); - GPU_writeStatus(ulStatusControl[4]); + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); #endif return 1; } @@ -2834,7 +2835,7 @@ void PaintPicDot(u8 * p,u8 c) #ifdef _WINDOWS void CALLBACK GPUgetScreenPic(u8 * pMem) #else -long CALLBACK GPU_getScreenPic(u8 * pMem) +long CALLBACK GPUgetScreenPic(u8 * pMem) #endif { float XS,YS;int x,y,v; @@ -2917,7 +2918,7 @@ long CALLBACK GPU_getScreenPic(u8 * pMem) #ifdef _WINDOWS void CALLBACK GPUshowScreenPic(u8 * pMem) #else -long CALLBACK GPU_showScreenPic(u8 * pMem) +long CALLBACK GPUshowScreenPic(u8 * pMem) #endif { // DestroyPic(); diff --git a/plugins/gpu-gles/gpuPlugin.h b/plugins/gpu-gles/gpuPlugin.h index c4520322..f5e91823 100644 --- a/plugins/gpu-gles/gpuPlugin.h +++ b/plugins/gpu-gles/gpuPlugin.h @@ -51,11 +51,11 @@ extern "C" { #include "plugin.h" #include #else -#ifndef MAEMO_CHANGES - #include "psxCommon.h" -#else - #include "../psxCommon.h" -#endif +//#ifndef MAEMO_CHANGES +// #include "psxCommon.h" +//#else +// #include "../psxCommon.h" +//#endif #include "gpuExternals.h" #ifdef __NANOGL__ #include @@ -87,32 +87,32 @@ typedef struct { u8 psxVRam[1024*1024*2]; } GPUFreeze_t; -long CALLBACK GPU_init(); -long CALLBACK GPU_shutdown(); -long CALLBACK GPU_open(int hwndGPU); -long CALLBACK GPU_close(); -unsigned long CALLBACK GPU_readData(void); -void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize); -unsigned long CALLBACK GPU_readStatus(void); -void CALLBACK GPU_writeData(unsigned long gdata); -void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize); -void CALLBACK GPU_writeStatus(unsigned long gdata); -long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr); -void CALLBACK GPU_updateLace(void); -void CALLBACK GPU_makeSnapshot(void); -long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF); -long CALLBACK GPU_getScreenPic(u8 * pMem); -long CALLBACK GPU_showScreenPic(u8 * pMem); -//void CALLBACK GPU_keypressed(int keycode); -//void CALLBACK GPU_displayText(s8 * pText); -//void CALLBACK GPU_clearDynarec(void (CALLBACK *callback)(void)); -long CALLBACK GPU_configure(void); -long CALLBACK GPU_test(void); -void CALLBACK GPU_about(void); +long CALLBACK GPUinit(); +long CALLBACK GPUshutdown(); +long CALLBACK GPUopen(int hwndGPU); +long CALLBACK GPUclose(); +unsigned long CALLBACK GPUreadData(void); +void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize); +unsigned long CALLBACK GPUreadStatus(void); +void CALLBACK GPUwriteData(unsigned long gdata); +void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize); +void CALLBACK GPUwriteStatus(unsigned long gdata); +long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr); +void CALLBACK GPUupdateLace(void); +void CALLBACK GPUmakeSnapshot(void); +long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF); +long CALLBACK GPUgetScreenPic(u8 * pMem); +long CALLBACK GPUshowScreenPic(u8 * pMem); +//void CALLBACK GPUkeypressed(int keycode); +//void CALLBACK GPUdisplayText(s8 * pText); +//void CALLBACK GPUclearDynarec(void (CALLBACK *callback)(void)); +long CALLBACK GPUconfigure(void); +long CALLBACK GPUtest(void); +void CALLBACK GPUabout(void); void DoSnapShot(void); -void GPU_vSinc(void); +void GPUvSinc(void); void updateDisplay(void); void updateFrontDisplay(void); void SetAutoFrameCap(void); diff --git a/plugins/gpu-gles/gpuPrim.c b/plugins/gpu-gles/gpuPrim.c index 9b718a5f..980d3dda 100644 --- a/plugins/gpu-gles/gpuPrim.c +++ b/plugins/gpu-gles/gpuPrim.c @@ -53,10 +53,10 @@ // globals //////////////////////////////////////////////////////////////////////// -#ifndef _WINDOWS -EGLSurface surface; -EGLDisplay display; -#endif +//#ifndef _WINDOWS +//EGLSurface surface; +//EGLDisplay display; +//#endif BOOL bDrawTextured; // current active drawing states BOOL bDrawSmoothShaded; diff --git a/plugins/gpu-gles/gpuStdafx.h b/plugins/gpu-gles/gpuStdafx.h index fc7ee3d5..bc348989 100644 --- a/plugins/gpu-gles/gpuStdafx.h +++ b/plugins/gpu-gles/gpuStdafx.h @@ -31,7 +31,9 @@ extern "C" { #endif - +#ifndef _GPU_API_ +#define _GPU_API_ 1 +#endif @@ -65,10 +67,16 @@ extern "C" { #pragma softfp_linkage #endif #ifdef MAEMO_CHANGES - #include + + //#include #include - #include - #include + //#include + #include + //#include "../maemo/minimal.h" + //#include + //#include + + #else #include // for opengl es types #include diff --git a/plugins/gpu-gles/gpuTexture.c b/plugins/gpu-gles/gpuTexture.c index d047a62f..98f8c9ce 100644 --- a/plugins/gpu-gles/gpuTexture.c +++ b/plugins/gpu-gles/gpuTexture.c @@ -76,26 +76,7 @@ #include "prim.h" #else #include "gpuStdafx.h" -#ifdef __NANOGL__ -#include -#include -#else -#ifdef SOFT_LINKAGE -#pragma softfp_linkage -#endif -#ifdef MAEMO_CHANGES - #include - #include - #include - #include -#else - #include // for opengl es types - #include -#endif -#ifdef SOFT_LINKAGE -#pragma no_softfp_linkage -#endif -#endif + #include "gpuDraw.h" //#include "plugins.h" #include "gpuExternals.h" -- 2.39.2 From f932e54bc49d2b211a9100f8b6f5385e0eafe64c Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 1 Jan 2011 21:04:40 +0200 Subject: [PATCH 16/16] gles: tweak Makefile, credits --- Makefile | 6 ++++- pandora/readme.txt | 27 +++++++++++++++------ plugins/gpu-gles/Makefile | 50 +++++++++++++++------------------------ 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 724fdbc8..673e768c 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,9 @@ $(TARGET): $(OBJS) spunull.so: plugins/spunull/spunull.c $(CC) $(CFLAGS) -shared -fPIC -ggdb -O2 -o $@ $^ +plugins/gpu-gles/gpuGLES.so: + make -C plugins/gpu-gles/ + clean: $(RM) $(TARGET) $(OBJS) @@ -97,7 +100,8 @@ PND_MAKE ?= $(HOME)/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh VER ?= $(shell git describe --abbrev=0 master) -rel: pcsx spunull.so pandora/pcsx.sh pandora/pcsx.pxml pandora/pcsx.png \ +rel: pcsx spunull.so plugins/gpu-gles/gpuGLES.so \ + pandora/pcsx.sh pandora/pcsx.pxml pandora/pcsx.png \ pandora/picorestore pandora/readme.txt skin COPYING rm -rf out mkdir -p out/plugins diff --git a/pandora/readme.txt b/pandora/readme.txt index 51ca33df..9a87e266 100644 --- a/pandora/readme.txt +++ b/pandora/readme.txt @@ -22,10 +22,10 @@ This version features a framebuffer driven menu that can be used to run games and configure the emulator. Supportd CD image formats: -- .cue/.bin -- .toc/.bin -- .img -- .mds +- .bin/.cue +- .bin/.toc +- .img/.ccd/.sub +- .mdf/.mds - .Z/.Z.table CDDA (CD audio) support requires .cue/.bin format. @@ -55,6 +55,8 @@ r1: Credits / License ----------------- +Emulator core: + (C) 1999-2003 PCSX Team (c) 1998 Vision Thing Linuzappz @@ -85,10 +87,21 @@ Credits / License Tristin Celestin (PulseAudio support) Wei Mingzhi (Maintainer, input plugin, iso/cheat support, misc stuff) -GPU and SPU code by Pete Bernert and the P.E.Op.S. team -ARM recompiler (C) 2009-2010 Ari64 +GLES plugin: + (C) 1999-2009 by Pete Bernert + EQ + Olli Hinkka + Proger + Pickle + +builtin GPU/SPU plugins: + Pete Bernert and the P.E.Op.S. team + +MIPS->ARM recompiler: + (C) 2009-2010 Ari64 -integration, optimization and frontend (C) 2010 notaz +integration, optimization and frontend: + (C) 2010-2011 notaz Source code is released under GNU GPL license, version 2 or later. See COPYING included in the archive (.pnd can be extracted using unsquashfs). diff --git a/plugins/gpu-gles/Makefile b/plugins/gpu-gles/Makefile index 48f84b89..fdefb08d 100644 --- a/plugins/gpu-gles/Makefile +++ b/plugins/gpu-gles/Makefile @@ -2,42 +2,30 @@ # MAKEFILE FOR PETE'S MESAGL GPU... just run "make" ############################################################################## -############################################################################## -# 1. SETS (CCFLAGS3 is used) -############################################################################## - -PREFIX = /mythtv/media/devel/toolchains/pandora/arm-2007q3 -TARGET = arm-none-linux-gnueabi- - -CC = $(PREFIX)/bin/$(TARGET)gcc +#PREFIX = /mythtv/media/devel/toolchains/pandora/arm-2007q3/ +CROSS_COMPILE ?= arm-none-linux-gnueabi- -CCFLAGS = -fPIC -c -Wall -O3 -ffast-math -fomit-frame-pointer -DMAEMO_CHANGES -DUSE_X11 +#CC = $(PREFIX)/bin/$(CROSS_COMPILE)gcc +CC = $(CROSS_COMPILE)gcc +CFLAGS += -fPIC # -Wall +CFLAGS += -O3 -ffast-math -fomit-frame-pointer +CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 +# note: the below causes strange bugs/crashes +#CFLAGS += -mfloat-abi=softfp +CFLAGS += -DMAEMO_CHANGES # -DUSE_X11 +CFLAGS += -I$(PREFIX)include -INCLUDE = -I$(PREFIX)/include -LINK = $(PREFIX)/bin/$(TARGET)gcc -LINKFLAGS = -shared -Wl,-soname,libgpuGLES.so -o libgpuGLES.so.1.0.0 -OBJ = gpuDraw.o gpuFps.o gpuPlugin.o gpuPrim.o gpuTexture.o +TARGET = gpuGLES.so +LDFLAGS += -shared -Wl,-soname,$(TARGET) -o $(TARGET) +LIB = -L$(PREFIX)lib -lGLES_CM -lX11 -lXau -lXdmcp -LIB = -L$(PREFIX)/lib -lGLES_CM -lX11 -lXau -lXdmcp -lstdc++ - -############################################################################## -# 2. MAIN RULE -############################################################################## +OBJ = gpuDraw.o gpuFps.o gpuPlugin.o gpuPrim.o gpuTexture.o -gpuPeopsMesaGL : $(OBJ) - $(LINK) $(LINKFLAGS) $(OBJ) $(LIB) +all: $(TARGET) -############################################################################## -# 3. GENERAL RULES -############################################################################## - -%.o : %.c - $(CC) $(CCFLAGS) $(INCLUDE) $< - -############################################################################## -# 4. SPECIFIC RULES -############################################################################## +$(TARGET): $(OBJ) + $(CC) $(LDFLAGS) $(OBJ) $(LIB) clean: - rm *.o libgpuGLES.so* \ No newline at end of file + $(RM) $(TARGET) $(OBJ) -- 2.39.2