diff --git a/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64mk2.dll b/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64mk2.dll index 9ba9b41ba5..be417a8d5c 100644 Binary files a/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64mk2.dll and b/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64mk2.dll differ diff --git a/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Main.cpp b/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Main.cpp index e88967a898..60816d492d 100644 --- a/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Main.cpp +++ b/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Main.cpp @@ -1,2702 +1,2733 @@ -/* -* Glide64 - Glide video plugin for Nintendo 64 emulators. -* Copyright (c) 2002 Dave2001 -* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski -* -* 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 -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//**************************************************************** -// -// Glide64 - Glide Plugin for Nintendo 64 emulators -// Project started on December 29th, 2001 -// -// Authors: -// Dave2001, original author, founded the project in 2001, left it in 2002 -// Gugaman, joined the project in 2002, left it in 2002 -// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 -// Hiroshi 'KoolSmoky' Morii, joined the project in 2007 -// -//**************************************************************** -// -// To modify Glide64: -// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. -// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. -// -//**************************************************************** - -#include "Gfx_1.3.h" -#include "Ini.h" -#include "Config.h" -#include "Util.h" -#include "3dmath.h" -#include "Debugger.h" -#include "Combine.h" -#include "TexCache.h" -#include "CRC.h" -#include "FBtoScreen.h" -#include "DepthBufferRender.h" - -#if defined(__GNUC__) -#include -#elif defined(__MSC__) -#include -#define PATH_MAX MAX_PATH -#endif -#include "osal_dynamiclib.h" -#ifdef TEXTURE_FILTER // Hiroshi Morii -#include -int ghq_dmptex_toggle_key = 0; -#endif -#if defined(__MINGW32__) -#define swprintf _snwprintf -#define vswprintf _vsnwprintf -#endif - -#define G64_VERSION "G64 Mk2" -#define RELTIME "Date: " __DATE__// " Time: " __TIME__ - -#ifdef EXT_LOGGING -std::ofstream extlog; -#endif - -#ifdef LOGGING -std::ofstream loga; -#endif - -#ifdef RDP_LOGGING -int log_open = FALSE; -std::ofstream rdp_log; -#endif - -#ifdef RDP_ERROR_LOG -int elog_open = FALSE; -std::ofstream rdp_err; -#endif - -GFX_INFO gfx; - -/* definitions of pointers to Core config functions */ -ptr_ConfigOpenSection ConfigOpenSection = NULL; -ptr_ConfigSetParameter ConfigSetParameter = NULL; -ptr_ConfigGetParameter ConfigGetParameter = NULL; -ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; -ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; -ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; -ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; -ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; -ptr_ConfigGetParamInt ConfigGetParamInt = NULL; -ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; -ptr_ConfigGetParamBool ConfigGetParamBool = NULL; -ptr_ConfigGetParamString ConfigGetParamString = NULL; - -ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; -ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; -ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; -ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; - -/* definitions of pointers to Core video extension functions */ -ptr_VidExt_Init CoreVideo_Init = NULL; -ptr_VidExt_Quit CoreVideo_Quit = NULL; -ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL; -ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; -ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; -ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; -ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; -ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL; -ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL; -ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL; -int to_fullscreen = FALSE; -int fullscreen = FALSE; -int romopen = FALSE; -GrContext_t gfx_context = 0; -int debugging = FALSE; -int exception = FALSE; - -int evoodoo = 0; -int ev_fullscreen = 0; - -#ifdef __WINDOWS__ -#define WINPROC_OVERRIDE -#endif - -#ifdef WINPROC_OVERRIDE -LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -WNDPROC oldWndProc = NULL; -WNDPROC myWndProc = NULL; -#endif - -#ifdef ALTTAB_FIX -HHOOK hhkLowLevelKybd = NULL; -LRESULT CALLBACK LowLevelKeyboardProc(int nCode, - WPARAM wParam, LPARAM lParam); -#endif - -#ifdef PERFORMANCE -int64 perf_cur; -int64 perf_next; -#endif - -#ifdef FPS -LARGE_INTEGER perf_freq; -LARGE_INTEGER fps_last; -LARGE_INTEGER fps_next; -float fps = 0.0f; -wxUint32 fps_count = 0; - -wxUint32 vi_count = 0; -float vi = 0.0f; - -wxUint32 region = 0; - -float ntsc_percent = 0.0f; -float pal_percent = 0.0f; - -#endif - -// ref rate -// 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff - -unsigned long BMASK = 0x7FFFFF; -// Reality display processor structure -RDP rdp; - -SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 }; - -HOTKEY_INFO hotkey_info; - -VOODOO voodoo = {0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - -GrTexInfo fontTex; -GrTexInfo cursorTex; -wxUint32 offset_font = 0; -wxUint32 offset_cursor = 0; -wxUint32 offset_textures = 0; -wxUint32 offset_texbuf1 = 0; - -int capture_screen = 0; -char capture_path[256]; - -SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1); - -// SOME FUNCTION DEFINITIONS - -static void DrawFrameBuffer (); - - -void (*renderCallback)(int) = NULL; -static void (*l_DebugCallback)(void *, int, const char *) = NULL; -static void *l_DebugCallContext = NULL; - -void _ChangeSize () -{ - rdp.scale_1024 = settings.scr_res_x / 1024.0f; - rdp.scale_768 = settings.scr_res_y / 768.0f; - -// float res_scl_x = (float)settings.res_x / 320.0f; - float res_scl_y = (float)settings.res_y / 240.0f; - - wxUint32 scale_x = *gfx.VI_X_SCALE_REG & 0xFFF; - if (!scale_x) return; - wxUint32 scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF; - if (!scale_y) return; - - float fscale_x = (float)scale_x / 1024.0f; - float fscale_y = (float)scale_y / 2048.0f; - - wxUint32 dwHStartReg = *gfx.VI_H_START_REG; - wxUint32 dwVStartReg = *gfx.VI_V_START_REG; - - wxUint32 hstart = dwHStartReg >> 16; - wxUint32 hend = dwHStartReg & 0xFFFF; - - // dunno... but sometimes this happens - if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x); - - wxUint32 vstart = dwVStartReg >> 16; - wxUint32 vend = dwVStartReg & 0xFFFF; - - rdp.vi_width = (hend - hstart) * fscale_x; - rdp.vi_height = (vend - vstart) * fscale_y * 1.0126582f; - float aspect = (settings.adjust_aspect && (fscale_y > fscale_x) && (rdp.vi_width > rdp.vi_height)) ? fscale_x/fscale_y : 1.0f; - -#ifdef LOGGING - sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend); - LOG (out_buf); - sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height); - LOG (out_buf); -#endif - - rdp.scale_x = (float)settings.res_x / rdp.vi_width; - if (region > 0 && settings.pal230) - { - // odd... but pal games seem to want 230 as height... - rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height) * aspect; - } - else - { - rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect; - } - // rdp.offset_x = settings.offset_x * res_scl_x; - // rdp.offset_y = settings.offset_y * res_scl_y; - //rdp.offset_x = 0; - // rdp.offset_y = 0; - rdp.offset_y = ((float)settings.res_y - rdp.vi_height * rdp.scale_y) * 0.5f; - if (((wxUint32)rdp.vi_width <= (*gfx.VI_WIDTH_REG)/2) && (rdp.vi_width > rdp.vi_height)) - rdp.scale_y *= 0.5f; - - rdp.scissor_o.ul_x = 0; - rdp.scissor_o.ul_y = 0; - rdp.scissor_o.lr_x = (wxUint32)rdp.vi_width; - rdp.scissor_o.lr_y = (wxUint32)rdp.vi_height; - - rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; -} - -void ChangeSize () -{ - if (debugging) - { - _ChangeSize (); - return; - } - switch (settings.aspectmode) - { - case 0: //4:3 - if (settings.scr_res_x >= settings.scr_res_y * 4.0f / 3.0f) { - settings.res_y = settings.scr_res_y; - settings.res_x = (wxUint32)(settings.res_y * 4.0f / 3.0f); - } else { - settings.res_x = settings.scr_res_x; - settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f); - } - break; - case 1: //16:9 - if (settings.scr_res_x >= settings.scr_res_y * 16.0f / 9.0f) { - settings.res_y = settings.scr_res_y; - settings.res_x = (wxUint32)(settings.res_y * 16.0f / 9.0f); - } else { - settings.res_x = settings.scr_res_x; - settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f); - } - break; - default: //stretch or original - settings.res_x = settings.scr_res_x; - settings.res_y = settings.scr_res_y; - } - _ChangeSize (); - rdp.offset_x = (settings.scr_res_x - settings.res_x) / 2.0f; - float offset_y = (settings.scr_res_y - settings.res_y) / 2.0f; - settings.res_x += (wxUint32)rdp.offset_x; - settings.res_y += (wxUint32)offset_y; - rdp.offset_y += offset_y; - if (settings.aspectmode == 3) // original - { - rdp.scale_x = rdp.scale_y = 1.0f; - rdp.offset_x = (settings.scr_res_x - rdp.vi_width) / 2.0f; - rdp.offset_y = (settings.scr_res_y - rdp.vi_height) / 2.0f; - } - // settings.res_x = settings.scr_res_x; - // settings.res_y = settings.scr_res_y; -} - -void ConfigWrapper() -{ - char strConfigWrapperExt[] = "grConfigWrapperExt"; - GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt); - if (grConfigWrapperExt) - grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic); -} -/* -static wxConfigBase * OpenIni() -{ - wxConfigBase * ini = wxConfigBase::Get(false); - if (!ini) - { - if (iniName.IsEmpty()) - iniName = pluginPath + wxT("/Glide64mk2.ini"); - if (wxFileExists(iniName)) - { - wxFileInputStream is(iniName); - wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1); - wxConfigBase::Set(fcfg); - ini = fcfg; - } - } - if (!ini) - wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION); - return ini; -} -*/ -#ifndef OLDAPI -void WriteLog(m64p_msg_level level, const char *msg, ...) -{ - char buf[1024]; - va_list args; - va_start(args, msg); - vsnprintf(buf, 1023, msg, args); - buf[1023]='\0'; - va_end(args); - if (l_DebugCallback) - { - l_DebugCallback(l_DebugCallContext, level, buf); - } -} -#endif - -void ReadSettings () -{ - // LOG("ReadSettings\n"); - if (!Config_Open()) - { - ERRLOG("Could not open configuration!"); - return; - } - - settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE); - //settings.lang_id not needed - // depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE); - settings.res_data = 0; - settings.scr_res_x = settings.res_x = Config_ReadScreenInt("ScreenWidth"); - settings.scr_res_y = settings.res_y = Config_ReadScreenInt("ScreenHeight"); - - settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0); - settings.ssformat = (BOOL)Config_ReadInt("ssformat", "TODO:ssformat", 0); - //settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0); - - settings.show_fps = (BYTE)Config_ReadInt ("show_fps", "Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent", 0, TRUE, FALSE); - settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0); - settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0); - // settings.advanced_options only good for GUI config - // settings.texenh_options = only good for GUI config - //settings.use_hotkeys = ini->Read(_T("hotkeys"), 1l); - - settings.wrpResolution = (BYTE)Config_ReadInt ("wrpResolution", "Wrapper resolution", 0, TRUE, FALSE); - settings.wrpVRAM = (BYTE)Config_ReadInt ("wrpVRAM", "Wrapper VRAM", 0, TRUE, FALSE); - settings.wrpFBO = (BOOL)Config_ReadInt ("wrpFBO", "Wrapper FBO", 1, TRUE, TRUE); - settings.wrpAnisotropic = (BOOL)Config_ReadInt ("wrpAnisotropic", "Wrapper Anisotropic Filtering", 0, TRUE, TRUE); - -#ifndef _ENDUSER_RELEASE_ - settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1); - settings.ucode = (wxUint32)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE); - settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0); - settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE); - - settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0); - settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0); - - settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0); - - settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0); - settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0); - settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0); - settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0); - settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0); -#else - settings.autodetect_ucode = TRUE; - settings.ucode = 2; - settings.wireframe = FALSE; - settings.wfmode = 0; - settings.logging = FALSE; - settings.log_clear = FALSE; - settings.run_in_window = FALSE; - settings.elogging = FALSE; - settings.filter_cache = FALSE; - settings.unk_as_red = FALSE; - settings.log_unk = FALSE; - settings.unk_clear = FALSE; -#endif - -#ifdef TEXTURE_FILTER - - // settings.ghq_fltr range is 0 through 6 - // Filters:\nApply a filter to either smooth or sharpen textures.\nThere are 4 different smoothing filters and 2 different sharpening filters.\nThe higher the number, the stronger the effect,\ni.e. \"Smoothing filter 4\" will have a much more noticeable effect than \"Smoothing filter 1\".\nBe aware that performance may have an impact depending on the game and/or the PC.\n[Recommended: your preference] - // _("None"), - // _("Smooth filtering 1"), - // _("Smooth filtering 2"), - // _("Smooth filtering 3"), - // _("Smooth filtering 4"), - // _("Sharp filtering 1"), - // _("Sharp filtering 2") - -// settings.ghq_cmpr 0=S3TC and 1=FXT1 - -//settings.ghq_ent is ___ -// "Texture enhancement:\n7 different filters are selectable here, each one with a distinctive look.\nBe aware of possible performance impacts.\n\nIMPORTANT: 'Store' mode - saves textures in cache 'as is'. It can improve performance in games, which load many textures.\nDisable 'Ignore backgrounds' option for better result.\n\n[Recommended: your preference]" - - - - settings.ghq_fltr = Config_ReadInt ("ghq_fltr", "Texture Enhancement: Smooth/Sharpen Filters", 0, TRUE, FALSE); - settings.ghq_cmpr = Config_ReadInt ("ghq_cmpr", "Texture Compression: 0 for S3TC, 1 for FXT1", 0, TRUE, FALSE); - settings.ghq_enht = Config_ReadInt ("ghq_enht", "Texture Enhancement: More filters", 0, TRUE, FALSE); - settings.ghq_hirs = Config_ReadInt ("ghq_hirs", "Hi-res texture pack format (0 for none, 1 for Rice)", 0, TRUE, FALSE); - settings.ghq_enht_cmpr = Config_ReadInt ("ghq_enht_cmpr", "Compress texture cache with S3TC or FXT1", 0, TRUE, TRUE); - settings.ghq_enht_tile = Config_ReadInt ("ghq_enht_tile", "Tile textures (saves memory but could cause issues)", 0, TRUE, FALSE); - settings.ghq_enht_f16bpp = Config_ReadInt ("ghq_enht_f16bpp", "Force 16bpp textures (saves ram but lower quality)", 0, TRUE, TRUE); - settings.ghq_enht_gz = Config_ReadInt ("ghq_enht_gz", "Compress texture cache", 1, TRUE, TRUE); - settings.ghq_enht_nobg = Config_ReadInt ("ghq_enht_nobg", "Don't enhance textures for backgrounds", 0, TRUE, TRUE); - settings.ghq_hirs_cmpr = Config_ReadInt ("ghq_hirs_cmpr", "Enable S3TC and FXT1 compression", 0, TRUE, TRUE); - settings.ghq_hirs_tile = Config_ReadInt ("ghq_hirs_tile", "Tile hi-res textures (saves memory but could cause issues)", 0, TRUE, TRUE); - settings.ghq_hirs_f16bpp = Config_ReadInt ("ghq_hirs_f16bpp", "Force 16bpp hi-res textures (saves ram but lower quality)", 0, TRUE, TRUE); - settings.ghq_hirs_gz = Config_ReadInt ("ghq_hirs_gz", "Compress hi-res texture cache", 1, TRUE, TRUE); - settings.ghq_hirs_altcrc = Config_ReadInt ("ghq_hirs_altcrc", "Alternative CRC calculation -- emulates Rice bug", 1, TRUE, TRUE); - settings.ghq_cache_save = Config_ReadInt ("ghq_cache_save", "Save tex cache to disk", 1, TRUE, TRUE); - settings.ghq_cache_size = Config_ReadInt ("ghq_cache_size", "Texture Cache Size (MB)", 128, TRUE, FALSE); - settings.ghq_hirs_let_texartists_fly = Config_ReadInt ("ghq_hirs_let_texartists_fly", "Use full alpha channel -- could cause issues for some tex packs", 0, TRUE, TRUE); - settings.ghq_hirs_dump = Config_ReadInt ("ghq_hirs_dump", "Dump textures", 0, FALSE, TRUE); -#endif - //TODO-PORT: remove? - ConfigWrapper(); -} - -void ReadSpecialSettings (const char * name) -{ - // char buf [256]; - // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name); - // LOG(buf); - settings.hacks = 0; - - //detect games which require special hacks - if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK")) - settings.hacks |= hack_Zelda; - else if (strstr(name, (const char *)"ROADSTERS TROPHY")) - settings.hacks |= hack_Zelda; - else if (strstr(name, (const char *)"Diddy Kong Racing")) - settings.hacks |= hack_Diddy; - else if (strstr(name, (const char *)"Tonic Trouble")) - settings.hacks |= hack_Tonic; - else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball")) - settings.hacks |= hack_ASB; - else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV")) - settings.hacks |= hack_BAR; - else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"J WORLD SOCCER3") || strstr(name, (const char *)"PERFECT STRIKER") || strstr(name, (const char *)"RONALDINHO SOCCER")) - settings.hacks |= hack_ISS64; - else if (strstr(name, (const char *)"MARIOKART64")) - settings.hacks |= hack_MK64; - else if (strstr(name, (const char *)"NITRO64")) - settings.hacks |= hack_WCWnitro; - else if (strstr(name, (const char *)"CHOPPER_ATTACK") || strstr(name, (const char *)"WILD CHOPPERS")) - settings.hacks |= hack_Chopper; - else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II")) - settings.hacks |= hack_RE2; - else if (strstr(name, (const char *)"YOSHI STORY")) - settings.hacks |= hack_Yoshi; - else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X")) - settings.hacks |= hack_Fzero; - else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY")) - settings.hacks |= hack_PMario; - else if (strstr(name, (const char *)"TOP GEAR RALLY 2")) - settings.hacks |= hack_TGR2; - else if (strstr(name, (const char *)"TOP GEAR RALLY")) - settings.hacks |= hack_TGR; - else if (strstr(name, (const char *)"Top Gear Hyper Bike")) - settings.hacks |= hack_Hyperbike; - else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD")) - settings.hacks |= hack_KI; - else if (strstr(name, (const char *)"Knockout Kings 2000")) - settings.hacks |= hack_Knockout; - else if (strstr(name, (const char *)"LEGORacers")) - settings.hacks |= hack_Lego; - else if (strstr(name, (const char *)"OgreBattle64")) - settings.hacks |= hack_Ogre64; - else if (strstr(name, (const char *)"Pilot Wings64")) - settings.hacks |= hack_Pilotwings; - else if (strstr(name, (const char *)"Supercross")) - settings.hacks |= hack_Supercross; - else if (strstr(name, (const char *)"STARCRAFT 64")) - settings.hacks |= hack_Starcraft; - else if (strstr(name, (const char *)"BANJO KAZOOIE 2") || strstr(name, (const char *)"BANJO TOOIE")) - settings.hacks |= hack_Banjo2; - else if (strstr(name, (const char *)"FIFA: RTWC 98") || strstr(name, (const char *)"RoadToWorldCup98")) - settings.hacks |= hack_Fifa98; - else if (strstr(name, (const char *)"Mega Man 64") || strstr(name, (const char *)"RockMan Dash")) - settings.hacks |= hack_Megaman; - else if (strstr(name, (const char *)"MISCHIEF MAKERS") || strstr(name, (const char *)"TROUBLE MAKERS")) - settings.hacks |= hack_Makers; - else if (strstr(name, (const char *)"GOLDENEYE")) - settings.hacks |= hack_GoldenEye; - else if (strstr(name, (const char *)"PUZZLE LEAGUE")) - settings.hacks |= hack_PPL; - - Ini * ini = Ini::OpenIni(); - if (!ini) - return; - ini->SetPath(name); - - ini->Read(_T("alt_tex_size"), &(settings.alt_tex_size)); - ini->Read(_T("use_sts1_only"), &(settings.use_sts1_only)); - ini->Read(_T("force_calc_sphere"), &(settings.force_calc_sphere)); - ini->Read(_T("correct_viewport"), &(settings.correct_viewport)); - ini->Read(_T("increase_texrect_edge"), &(settings.increase_texrect_edge)); - ini->Read(_T("decrease_fillrect_edge"), &(settings.decrease_fillrect_edge)); - if (ini->Read(_T("texture_correction"), -1) == 0) settings.texture_correction = 0; - else settings.texture_correction = 1; - if (ini->Read(_T("pal230"), -1) == 1) settings.pal230 = 1; - else settings.pal230 = 0; - ini->Read(_T("stipple_mode"), &(settings.stipple_mode)); - int stipple_pattern = ini->Read(_T("stipple_pattern"), -1); - if (stipple_pattern > 0) settings.stipple_pattern = (wxUint32)stipple_pattern; - ini->Read(_T("force_microcheck"), &(settings.force_microcheck)); - ini->Read(_T("force_quad3d"), &(settings.force_quad3d)); - ini->Read(_T("clip_zmin"), &(settings.clip_zmin)); - ini->Read(_T("clip_zmax"), &(settings.clip_zmax)); - ini->Read(_T("fast_crc"), &(settings.fast_crc)); - ini->Read(_T("adjust_aspect"), &(settings.adjust_aspect), 1); - ini->Read(_T("zmode_compare_less"), &(settings.zmode_compare_less)); - ini->Read(_T("old_style_adither"), &(settings.old_style_adither)); - ini->Read(_T("n64_z_scale"), &(settings.n64_z_scale)); - if (settings.n64_z_scale) - ZLUT_init(); - - //frame buffer - int optimize_texrect = ini->Read(_T("optimize_texrect"), -1); - int ignore_aux_copy = ini->Read(_T("ignore_aux_copy"), -1); - int hires_buf_clear = ini->Read(_T("hires_buf_clear"), -1); - int read_alpha = ini->Read(_T("fb_read_alpha"), -1); - int useless_is_useless = ini->Read(_T("useless_is_useless"), -1); - int fb_crc_mode = ini->Read(_T("fb_crc_mode"), -1); - - if (optimize_texrect > 0) settings.frame_buffer |= fb_optimize_texrect; - else if (optimize_texrect == 0) settings.frame_buffer &= ~fb_optimize_texrect; - if (ignore_aux_copy > 0) settings.frame_buffer |= fb_ignore_aux_copy; - else if (ignore_aux_copy == 0) settings.frame_buffer &= ~fb_ignore_aux_copy; - if (hires_buf_clear > 0) settings.frame_buffer |= fb_hwfbe_buf_clear; - else if (hires_buf_clear == 0) settings.frame_buffer &= ~fb_hwfbe_buf_clear; - if (read_alpha > 0) settings.frame_buffer |= fb_read_alpha; - else if (read_alpha == 0) settings.frame_buffer &= ~fb_read_alpha; - if (useless_is_useless > 0) settings.frame_buffer |= fb_useless_is_useless; - else settings.frame_buffer &= ~fb_useless_is_useless; - if (fb_crc_mode >= 0) settings.fb_crc_mode = (SETTINGS::FBCRCMODE)fb_crc_mode; - - // if (settings.custom_ini) - { - ini->Read(_T("filtering"), &(settings.filtering)); - ini->Read(_T("fog"), &(settings.fog)); - ini->Read(_T("buff_clear"), &(settings.buff_clear)); - ini->Read(_T("swapmode"), &(settings.swapmode)); - ini->Read(_T("aspect"), &(settings.aspectmode)); - ini->Read(_T("lodmode"), &(settings.lodmode)); - /* - TODO-port: fix resolutions - int resolution; - if (ini->Read(_T("resolution"), &resolution)) - { - settings.res_data = (wxUint32)resolution; - if (settings.res_data >= 0x18) settings.res_data = 12; - settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0]; - settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1]; - } - */ - - PackedScreenResolution tmpRes = Config_ReadScreenSettings(); - settings.res_data = tmpRes.resolution; - settings.scr_res_x = settings.res_x = tmpRes.width; - settings.scr_res_y = settings.res_y = tmpRes.height; - - //frame buffer - int smart_read = ini->Read(_T("fb_smart"), -1); - int hires = ini->Read(_T("fb_hires"), -1); - int read_always = ini->Read(_T("fb_read_always"), -1); - int read_back_to_screen = ini->Read(_T("read_back_to_screen"), -1); - int cpu_write_hack = ini->Read(_T("detect_cpu_write"), -1); - int get_fbinfo = ini->Read(_T("fb_get_info"), -1); - int depth_render = ini->Read(_T("fb_render"), -1); - - if (smart_read > 0) settings.frame_buffer |= fb_emulation; - else if (smart_read == 0) settings.frame_buffer &= ~fb_emulation; - if (hires > 0) settings.frame_buffer |= fb_hwfbe; - else if (hires == 0) settings.frame_buffer &= ~fb_hwfbe; - if (read_always > 0) settings.frame_buffer |= fb_ref; - else if (read_always == 0) settings.frame_buffer &= ~fb_ref; - if (read_back_to_screen == 1) settings.frame_buffer |= fb_read_back_to_screen; - else if (read_back_to_screen == 2) settings.frame_buffer |= fb_read_back_to_screen2; - else if (read_back_to_screen == 0) settings.frame_buffer &= ~(fb_read_back_to_screen|fb_read_back_to_screen2); - if (cpu_write_hack > 0) settings.frame_buffer |= fb_cpu_write_hack; - else if (cpu_write_hack == 0) settings.frame_buffer &= ~fb_cpu_write_hack; - if (get_fbinfo > 0) settings.frame_buffer |= fb_get_info; - else if (get_fbinfo == 0) settings.frame_buffer &= ~fb_get_info; - if (depth_render > 0) settings.frame_buffer |= fb_depth_render; - else if (depth_render == 0) settings.frame_buffer &= ~fb_depth_render; - settings.frame_buffer |= fb_motionblur; - } - settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled; -} - -//TODO-PORT: more ini stuff -void WriteSettings (bool saveEmulationSettings) -{ -/* - wxConfigBase * ini = OpenIni(); - if (!ini || !ini->HasGroup(_T("/SETTINGS"))) - return; - ini->SetPath(_T("/SETTINGS")); - - ini->Write(_T("card_id"), settings.card_id); - ini->Write(_T("lang_id"), settings.lang_id); - ini->Write(_T("resolution"), (int)settings.res_data); - ini->Write(_T("ssformat"), settings.ssformat); - ini->Write(_T("vsync"), settings.vsync); - ini->Write(_T("show_fps"), settings.show_fps); - ini->Write(_T("clock"), settings.clock); - ini->Write(_T("clock_24_hr"), settings.clock_24_hr); - ini->Write(_T("advanced_options"), settings.advanced_options); - ini->Write(_T("texenh_options"), settings.texenh_options); - - ini->Write(_T("wrpResolution"), settings.wrpResolution); - ini->Write(_T("wrpVRAM"), settings.wrpVRAM); - ini->Write(_T("wrpFBO"), settings.wrpFBO); - ini->Write(_T("wrpAnisotropic"), settings.wrpAnisotropic); - -#ifndef _ENDUSER_RELEASE_ - ini->Write(_T("autodetect_ucode"), settings.autodetect_ucode); - ini->Write(_T("ucode"), (int)settings.ucode); - ini->Write(_T("wireframe"), settings.wireframe); - ini->Write(_T("wfmode"), settings.wfmode); - ini->Write(_T("logging"), settings.logging); - ini->Write(_T("log_clear"), settings.log_clear); - ini->Write(_T("run_in_window"), settings.run_in_window); - ini->Write(_T("elogging"), settings.elogging); - ini->Write(_T("filter_cache"), settings.filter_cache); - ini->Write(_T("unk_as_red"), settings.unk_as_red); - ini->Write(_T("log_unk"), settings.log_unk); - ini->Write(_T("unk_clear"), settings.unk_clear); -#endif //_ENDUSER_RELEASE_ - -#ifdef TEXTURE_FILTER - ini->Write(_T("ghq_fltr"), settings.ghq_fltr); - ini->Write(_T("ghq_cmpr"), settings.ghq_cmpr); - ini->Write(_T("ghq_enht"), settings.ghq_enht); - ini->Write(_T("ghq_hirs"), settings.ghq_hirs); - ini->Write(_T("ghq_enht_cmpr"), settings.ghq_enht_cmpr); - ini->Write(_T("ghq_enht_tile"), settings.ghq_enht_tile); - ini->Write(_T("ghq_enht_f16bpp"), settings.ghq_enht_f16bpp); - ini->Write(_T("ghq_enht_gz"), settings.ghq_enht_gz); - ini->Write(_T("ghq_enht_nobg"), settings.ghq_enht_nobg); - ini->Write(_T("ghq_hirs_cmpr"), settings.ghq_hirs_cmpr); - ini->Write(_T("ghq_hirs_tile"), settings.ghq_hirs_tile); - ini->Write(_T("ghq_hirs_f16bpp"), settings.ghq_hirs_f16bpp); - ini->Write(_T("ghq_hirs_gz"), settings.ghq_hirs_gz); - ini->Write(_T("ghq_hirs_altcrc"), settings.ghq_hirs_altcrc); - ini->Write(_T("ghq_cache_save"), settings.ghq_cache_save); - ini->Write(_T("ghq_cache_size"), settings.ghq_cache_size); - ini->Write(_T("ghq_hirs_let_texartists_fly"), settings.ghq_hirs_let_texartists_fly); - ini->Write(_T("ghq_hirs_dump"), settings.ghq_hirs_dump); -#endif - - if (saveEmulationSettings) - { - if (romopen) - { - wxString S = _T("/"); - ini->SetPath(S+rdp.RomName); - } - else - ini->SetPath(_T("/DEFAULT")); - ini->Write(_T("filtering"), settings.filtering); - ini->Write(_T("fog"), settings.fog); - ini->Write(_T("buff_clear"), settings.buff_clear); - ini->Write(_T("swapmode"), settings.swapmode); - ini->Write(_T("lodmode"), settings.lodmode); - ini->Write(_T("aspect"), settings.aspectmode); - - ini->Write(_T("fb_read_always"), settings.frame_buffer&fb_ref ? 1 : 0l); - ini->Write(_T("fb_smart"), settings.frame_buffer & fb_emulation ? 1 : 0l); - // ini->Write("motionblur", settings.frame_buffer & fb_motionblur ? 1 : 0); - ini->Write(_T("fb_hires"), settings.frame_buffer & fb_hwfbe ? 1 : 0l); - ini->Write(_T("fb_get_info"), settings.frame_buffer & fb_get_info ? 1 : 0l); - ini->Write(_T("fb_render"), settings.frame_buffer & fb_depth_render ? 1 : 0l); - ini->Write(_T("detect_cpu_write"), settings.frame_buffer & fb_cpu_write_hack ? 1 : 0l); - if (settings.frame_buffer & fb_read_back_to_screen) - ini->Write(_T("read_back_to_screen"), 1); - else if (settings.frame_buffer & fb_read_back_to_screen2) - ini->Write(_T("read_back_to_screen"), 2); - else - ini->Write(_T("read_back_to_screen"), 0l); - } - - wxFileOutputStream os(iniName); - ((wxFileConfig*)ini)->Save(os); -*/ -} - -GRTEXBUFFEREXT grTextureBufferExt = NULL; -GRTEXBUFFEREXT grTextureAuxBufferExt = NULL; -GRAUXBUFFEREXT grAuxBufferExt = NULL; -GRSTIPPLE grStippleModeExt = NULL; -GRSTIPPLE grStipplePatternExt = NULL; -FxBool (FX_CALL *grKeyPressed)(FxU32) = NULL; - -int GetTexAddrUMA(int tmu, int texsize) -{ - int addr = voodoo.tex_min_addr[0] + voodoo.tmem_ptr[0]; - voodoo.tmem_ptr[0] += texsize; - voodoo.tmem_ptr[1] = voodoo.tmem_ptr[0]; - return addr; -} -int GetTexAddrNonUMA(int tmu, int texsize) -{ - int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu]; - voodoo.tmem_ptr[tmu] += texsize; - return addr; -} -GETTEXADDR GetTexAddr = GetTexAddrNonUMA; - -// guLoadTextures - used to load the cursor and font textures -void guLoadTextures () -{ - if (grTextureBufferExt) - { - int tbuf_size = 0; - if (voodoo.max_tex_size <= 256) - { - grTextureBufferExt( GR_TMU1, voodoo.tex_min_addr[GR_TMU1], GR_LOD_LOG2_256, GR_LOD_LOG2_256, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); - tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); - } - else if (settings.scr_res_x <= 1024) - { - grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); - tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); - grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); - grBufferClear (0, 0, 0xFFFF); - grRenderBuffer( GR_BUFFER_BACKBUFFER ); - } - else - { - grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); - tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); - grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); - grBufferClear (0, 0, 0xFFFF); - grRenderBuffer( GR_BUFFER_BACKBUFFER ); - } - - rdp.texbufs[0].tmu = GR_TMU0; - rdp.texbufs[0].begin = voodoo.tex_min_addr[GR_TMU0]; - rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size; - rdp.texbufs[0].count = 0; - rdp.texbufs[0].clear_allowed = TRUE; - offset_font = tbuf_size; - if (voodoo.num_tmu > 1) - { - rdp.texbufs[1].tmu = GR_TMU1; - rdp.texbufs[1].begin = voodoo.tex_UMA ? rdp.texbufs[0].end : voodoo.tex_min_addr[GR_TMU1]; - rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size; - rdp.texbufs[1].count = 0; - rdp.texbufs[1].clear_allowed = TRUE; - if (voodoo.tex_UMA) - offset_font += tbuf_size; - else - offset_texbuf1 = tbuf_size; - } - } - else - offset_font = 0; - -#include "font.h" - wxUint32 *data = (wxUint32*)font; - wxUint32 cur; - - // ** Font texture ** - wxUint8 *tex8 = (wxUint8*)malloc(256*64); - - fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256; - fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1; - fontTex.format = GR_TEXFMT_ALPHA_8; - fontTex.data = tex8; - - // Decompression: [1-bit inverse alpha --> 8-bit alpha] - wxUint32 i,b; - for (i=0; i<0x200; i++) - { - // cur = ~*(data++), byteswapped -#ifdef __VISUALC__ - cur = _byteswap_ulong(~*(data++)); -#else - cur = ~*(data++); - cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF); -#endif - - for (b=0x80000000; b!=0; b>>=1) - { - if (cur&b) *tex8 = 0xFF; - else *tex8 = 0x00; - tex8 ++; - } - } - - grTexDownloadMipMap (GR_TMU0, - voodoo.tex_min_addr[GR_TMU0] + offset_font, - GR_MIPMAPLEVELMASK_BOTH, - &fontTex); - - offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex); - - free (fontTex.data); - - // ** Cursor texture ** -#include "cursor.h" - data = (wxUint32*)cursor; - - wxUint16 *tex16 = (wxUint16*)malloc(32*32*2); - - cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32; - cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; - cursorTex.format = GR_TEXFMT_ARGB_1555; - cursorTex.data = tex16; - - // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555] - for (i=0; i<0x200; i++) - { - cur = *(data++); - *(tex16++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8)); - *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24)); - } - - grTexDownloadMipMap (GR_TMU0, - voodoo.tex_min_addr[GR_TMU0] + offset_cursor, - GR_MIPMAPLEVELMASK_BOTH, - &cursorTex); - - // Round to higher 16 - offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex)) - & 0xFFFFFFF0) + 16; - free (cursorTex.data); -} - -#ifdef TEXTURE_FILTER -void DisplayLoadProgress(const wchar_t *format, ...) -{ - va_list args; - wchar_t wbuf[INFO_BUF]; - char buf[INFO_BUF]; - - // process input - va_start(args, format); - vswprintf(wbuf, INFO_BUF, format, args); - va_end(args); - - // XXX: convert to multibyte - wcstombs(buf, wbuf, INFO_BUF); - - if (fullscreen) - { - float x; - set_message_combiner (); - output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT..."); - int len = min (strlen(buf)*8, 1024); - x = (1024-len)/2.0f; - output (x, 360, 1, buf); - grBufferSwap (0); - grColorMask (FXTRUE, FXTRUE); - grBufferClear (0, 0, 0xFFFF); - } -} -#endif - -int InitGfx () -{ -#ifdef TEXTURE_FILTER - wchar_t romname[256]; - wchar_t foldername[PATH_MAX + 64]; - wchar_t cachename[PATH_MAX + 64]; -#endif - if (fullscreen) - ReleaseGfx (); - - OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it - OPEN_RDP_E_LOG (); - VLOG ("InitGfx ()\n"); - - debugging = FALSE; - rdp_reset (); - - // Initialize Glide - grGlideInit (); - - // Select the Glide device - grSstSelect (settings.card_id); - - // Is mirroring allowed? - const char *extensions = grGetString (GR_EXTENSION); - - // Check which SST we are using and initialize stuff - // Hiroshi Morii - enum { - GR_SSTTYPE_VOODOO = 0, - GR_SSTTYPE_SST96 = 1, - GR_SSTTYPE_AT3D = 2, - GR_SSTTYPE_Voodoo2 = 3, - GR_SSTTYPE_Banshee = 4, - GR_SSTTYPE_Voodoo3 = 5, - GR_SSTTYPE_Voodoo4 = 6, - GR_SSTTYPE_Voodoo5 = 7 - }; - const char *hardware = grGetString(GR_HARDWARE); - unsigned int SST_type = GR_SSTTYPE_VOODOO; - if (strstr(hardware, "Rush")) { - SST_type = GR_SSTTYPE_SST96; - } else if (strstr(hardware, "Voodoo2")) { - SST_type = GR_SSTTYPE_Voodoo2; - } else if (strstr(hardware, "Voodoo Banshee")) { - SST_type = GR_SSTTYPE_Banshee; - } else if (strstr(hardware, "Voodoo3")) { - SST_type = GR_SSTTYPE_Voodoo3; - } else if (strstr(hardware, "Voodoo4")) { - SST_type = GR_SSTTYPE_Voodoo4; - } else if (strstr(hardware, "Voodoo5")) { - SST_type = GR_SSTTYPE_Voodoo5; - } - // 2Mb Texture boundary - voodoo.has_2mb_tex_boundary = (SST_type < GR_SSTTYPE_Banshee) && !evoodoo; - // use UMA if available - voodoo.tex_UMA = FALSE; - //* - if (strstr(extensions, " TEXUMA ")) { - // we get better texture cache hits with UMA on - grEnable(GR_TEXTURE_UMA_EXT); - voodoo.tex_UMA = TRUE; - LOG ("Using TEXUMA extension.\n"); - } - //*/ -//TODO-PORT: fullscreen stuff - wxUint32 res_data = settings.res_data; - char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt"; - if (ev_fullscreen) - { - GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt = - (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt); - if (grWrapperFullScreenResolutionExt) { - wxUint32 _width, _height = 0; - settings.res_data = grWrapperFullScreenResolutionExt(&_width, &_height); - settings.scr_res_x = settings.res_x = _width; - settings.scr_res_y = settings.res_y = _height; - } - res_data = settings.res_data; - } - else if (evoodoo) - { - GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt = - (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt); - if (grWrapperFullScreenResolutionExt != NULL) - { -/* - TODO-port: fix resolutions - settings.res_data = settings.res_data_org; - settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0]; - settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1]; -*/ - } - res_data = settings.res_data | 0x80000000; - } - - gfx_context = 0; - - // Select the window - - if (fb_hwfbe_enabled) - { - char strSstWinOpenExt[] ="grSstWinOpenExt"; - GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt); - if (grSstWinOpenExt) - gfx_context = grSstWinOpenExt ((FxU32)NULL, - res_data, - GR_REFRESH_60Hz, - GR_COLORFORMAT_RGBA, - GR_ORIGIN_UPPER_LEFT, - fb_emulation_enabled?GR_PIXFMT_RGB_565:GR_PIXFMT_ARGB_8888, //32b color is not compatible with fb emulation - 2, // Double-buffering - 1); // 1 auxillary buffer - } - if (!gfx_context) - gfx_context = grSstWinOpen ((FxU32)NULL, - res_data, - GR_REFRESH_60Hz, - GR_COLORFORMAT_RGBA, - GR_ORIGIN_UPPER_LEFT, - 2, // Double-buffering - 1); // 1 auxillary buffer - - if (!gfx_context) - { - ERRLOG("Error setting display mode"); - // grSstWinClose (gfx_context); - grGlideShutdown (); - return FALSE; - } - - fullscreen = TRUE; - to_fullscreen = FALSE; - - - // get the # of TMUs available - grGet (GR_NUM_TMU, 4, (FxI32*)&voodoo.num_tmu); - // get maximal texture size - grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32*)&voodoo.max_tex_size); - voodoo.sup_large_tex = (voodoo.max_tex_size > 256 && !(settings.hacks & hack_PPL)); - - //num_tmu = 1; - if (voodoo.tex_UMA) - { - GetTexAddr = GetTexAddrUMA; - voodoo.tex_min_addr[0] = voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU0); - voodoo.tex_max_addr[0] = voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU0); - } - else - { - GetTexAddr = GetTexAddrNonUMA; - voodoo.tex_min_addr[0] = grTexMinAddress(GR_TMU0); - voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU1); - voodoo.tex_max_addr[0] = grTexMaxAddress(GR_TMU0); - voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU1); - } - - if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring - voodoo.sup_mirroring = 1; - else - voodoo.sup_mirroring = 0; - - if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension - voodoo.sup_32bit_tex = TRUE; - else - voodoo.sup_32bit_tex = FALSE; - - voodoo.gamma_correction = 0; - if (strstr(extensions, "GETGAMMA")) - grGet(GR_GAMMA_TABLE_ENTRIES, sizeof(voodoo.gamma_table_size), &voodoo.gamma_table_size); - - if (fb_hwfbe_enabled) - { - if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER")) - { - if (!strncmp(extstr, "TEXTUREBUFFER", 13)) - { - char strTextureBufferExt[] = "grTextureBufferExt"; - grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureBufferExt); - char strTextureAuxBufferExt[] = "grTextureAuxBufferExt"; - grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureAuxBufferExt); - char strAuxBufferExt[] = "grAuxBufferExt"; - grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress(strAuxBufferExt); - } - } - else - settings.frame_buffer &= ~fb_hwfbe; - } - else - grTextureBufferExt = 0; - - grStippleModeExt = (GRSTIPPLE)grStippleMode; - grStipplePatternExt = (GRSTIPPLE)grStipplePattern; - - if (grStipplePatternExt) - grStipplePatternExt(settings.stipple_pattern); - -// char strKeyPressedExt[] = "grKeyPressedExt"; -// grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt); - - InitCombine(); - -#ifdef SIMULATE_VOODOO1 - voodoo.num_tmu = 1; - voodoo.sup_mirroring = 0; -#endif - -#ifdef SIMULATE_BANSHEE - voodoo.num_tmu = 1; - voodoo.sup_mirroring = 1; -#endif - - grCoordinateSpace (GR_WINDOW_COORDS); - grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE); - grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE); - grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE); - grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE); - grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE); - grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE); - - grCullMode(GR_CULL_NEGATIVE); - - if (settings.fog) //"FOGCOORD" extension - { - if (strstr (extensions, "FOGCOORD")) - { - GrFog_t fog_t[64]; - guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f); - - for (int i = 63; i > 0; i--) - { - if (fog_t[i] - fog_t[i-1] > 63) - { - fog_t[i-1] = fog_t[i] - 63; - } - } - fog_t[0] = 0; - // for (int f = 0; f < 64; f++) - // { - // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f)); - // } - grFogTable (fog_t); - grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE); - } - else //not supported - settings.fog = FALSE; - } - - grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER); - grDepthBufferFunction(GR_CMP_LESS); - grDepthMask(FXTRUE); - - settings.res_x = settings.scr_res_x; - settings.res_y = settings.scr_res_y; - ChangeSize (); - - guLoadTextures (); - ClearCache (); - - grCullMode (GR_CULL_DISABLE); - grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER); - grDepthBufferFunction (GR_CMP_ALWAYS); - grRenderBuffer(GR_BUFFER_BACKBUFFER); - grColorMask (FXTRUE, FXTRUE); - grDepthMask (FXTRUE); - grBufferClear (0, 0, 0xFFFF); - grBufferSwap (0); - grBufferClear (0, 0, 0xFFFF); - grDepthMask (FXFALSE); - grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR); - grTexFilterMode (1, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR); - grTexClampMode (0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); - grTexClampMode (1, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); - grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); - rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; - -#ifdef TEXTURE_FILTER // Hiroshi Morii - if (!settings.ghq_use) - { - settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs; - if (settings.ghq_use) - { - /* Plugin path */ - int options = texfltr[settings.ghq_fltr]|texenht[settings.ghq_enht]|texcmpr[settings.ghq_cmpr]|texhirs[settings.ghq_hirs]; - if (settings.ghq_enht_cmpr) - options |= COMPRESS_TEX; - if (settings.ghq_hirs_cmpr) - options |= COMPRESS_HIRESTEX; - // if (settings.ghq_enht_tile) - // options |= TILE_TEX; - if (settings.ghq_hirs_tile) - options |= TILE_HIRESTEX; - if (settings.ghq_enht_f16bpp) - options |= FORCE16BPP_TEX; - if (settings.ghq_hirs_f16bpp) - options |= FORCE16BPP_HIRESTEX; - if (settings.ghq_enht_gz) - options |= GZ_TEXCACHE; - if (settings.ghq_hirs_gz) - options |= GZ_HIRESTEXCACHE; - if (settings.ghq_cache_save) - options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE); - if (settings.ghq_hirs_let_texartists_fly) - options |= LET_TEXARTISTS_FLY; - if (settings.ghq_hirs_dump) - options |= DUMP_TEX; - - ghq_dmptex_toggle_key = 0; - - swprintf(romname, sizeof(romname) / sizeof(*romname), L"%hs", rdp.RomName); - swprintf(foldername, sizeof(foldername) / sizeof(*foldername), L"%hs", ConfigGetUserDataPath()); - swprintf(cachename, sizeof(cachename) / sizeof(*cachename), L"%hs", ConfigGetUserCachePath()); - - settings.ghq_use = (int)ext_ghq_init(voodoo.max_tex_size, // max texture width supported by hardware - voodoo.max_tex_size, // max texture height supported by hardware - voodoo.sup_32bit_tex?32:16, // max texture bpp supported by hardware - options, - settings.ghq_cache_size * 1024*1024, // cache texture to system memory - foldername, - cachename, - romname, // name of ROM. must be no longer than 256 characters - DisplayLoadProgress); - } - } - if (settings.ghq_use && strstr (extensions, "TEXMIRROR")) - voodoo.sup_mirroring = 1; -#endif - - return TRUE; -} - -void ReleaseGfx () -{ - VLOG("ReleaseGfx ()\n"); - - // Restore gamma settings - if (voodoo.gamma_correction) - { - if (voodoo.gamma_table_r) - grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); - else - guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop - voodoo.gamma_correction = 0; - } - - // Release graphics - grSstWinClose (gfx_context); - - // Shutdown glide - grGlideShutdown(); - - fullscreen = FALSE; - rdp.window_changed = TRUE; -} - -// new API code begins here! - -#ifdef __cplusplus -extern "C" { -#endif - -EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front) -{ - VLOG("CALL ReadScreen2 ()\n"); - *width = settings.res_x; - *height = settings.res_y; - if (dest) - { - BYTE * line = (BYTE*)dest; - if (!fullscreen) - { - for (wxUint32 y=0; y - if (settings.ghq_use) - { - ext_ghq_shutdown(); - settings.ghq_use = 0; - } -#endif - if (fullscreen) - ReleaseGfx (); - ZLUT_release(); - ClearCache (); - delete[] voodoo.gamma_table_r; - voodoo.gamma_table_r = 0; - delete[] voodoo.gamma_table_g; - voodoo.gamma_table_g = 0; - delete[] voodoo.gamma_table_b; - voodoo.gamma_table_b = 0; -} - -/****************************************************************** -Function: DllTest -Purpose: This function is optional function that is provided -to allow the user to test the dll -input: a handle to the window that calls this function -output: none -*******************************************************************/ -void CALL DllTest ( HWND hParent ) -{ -} - -/****************************************************************** -Function: DrawScreen -Purpose: This function is called when the emulator receives a -WM_PAINT message. This allows the gfx to fit in when -it is being used in the desktop. -input: none -output: none -*******************************************************************/ -void CALL DrawScreen (void) -{ - VLOG ("DrawScreen ()\n"); -} - -/****************************************************************** -Function: GetDllInfo -Purpose: This function allows the emulator to gather information -about the dll by filling in the PluginInfo structure. -input: a pointer to a PLUGIN_INFO stucture that needs to be -filled by the function. (see def above) -output: none -*******************************************************************/ -void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo ) -{ - VLOG ("GetDllInfo ()\n"); - PluginInfo->Version = 0x0103; // Set to 0x0103 - PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX - sprintf (PluginInfo->Name, "Glide64mk2 " G64_VERSION RELTIME); // Name of the DLL - - // If DLL supports memory these memory options then set them to TRUE or FALSE - // if it does not support it - PluginInfo->NormalMemory = TRUE; // a normal wxUint8 array - PluginInfo->MemoryBswaped = TRUE; // a normal wxUint8 array where the memory has been pre - // bswap on a dword (32 bits) boundry -} - -#ifndef WIN32 -BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) -{ - struct timeval tv; - - /* generic routine */ - gettimeofday( &tv, NULL ); - counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000; - return TRUE; -} - -BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) -{ - frequency->s.LowPart= 1000000; - frequency->s.HighPart= 0; - return TRUE; -} -#endif - -/****************************************************************** -Function: InitiateGFX -Purpose: This function is called when the DLL is started to give -information from the emulator that the n64 graphics -uses. This is not called from the emulation thread. -Input: Gfx_Info is passed to this function which is defined -above. -Output: TRUE on success -FALSE on failure to initialise - -** note on interrupts **: -To generate an interrupt set the appropriate bit in MI_INTR_REG -and then call the function CheckInterrupts to tell the emulator -that there is a waiting interrupt. -*******************************************************************/ - -EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info) -{ - VLOG ("InitiateGFX (*)\n"); - voodoo.num_tmu = 2; - - // Assume scale of 1 for debug purposes - rdp.scale_x = 1.0f; - rdp.scale_y = 1.0f; - - memset (&settings, 0, sizeof(SETTINGS)); - ReadSettings (); - char name[21] = "DEFAULT"; - ReadSpecialSettings (name); - settings.res_data_org = settings.res_data; -#ifdef FPS - QueryPerformanceFrequency (&perf_freq); - QueryPerformanceCounter (&fps_last); -#endif - - debug_init (); // Initialize debugger - - gfx = Gfx_Info; - -#ifdef WINPROC_OVERRIDE - // [H.Morii] inject our own winproc so that "alt-enter to fullscreen" - // message is shown when the emulator window is activated. - WNDPROC curWndProc = (WNDPROC)GetWindowLong(gfx.hWnd, GWL_WNDPROC); - if (curWndProc && curWndProc != (WNDPROC)WndProc) { - oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)WndProc); - } -#endif - - util_init (); - math_init (); - TexCacheInit (); - CRC_BuildTable(); - CountCombine(); - if (fb_depth_render_enabled) - ZLUT_init(); - - char strConfigWrapperExt[] = "grConfigWrapperExt"; - GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt); - if (grConfigWrapperExt) - grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic); - - grGlideInit (); - grSstSelect (0); - const char *extensions = grGetString (GR_EXTENSION); - grGlideShutdown (); - if (strstr (extensions, "EVOODOO")) - { - evoodoo = 1; - voodoo.has_2mb_tex_boundary = 0; - } - else { - evoodoo = 0; - voodoo.has_2mb_tex_boundary = 1; - } - - return TRUE; -} - -/****************************************************************** -Function: MoveScreen -Purpose: This function is called in response to the emulator -receiving a WM_MOVE passing the xpos and ypos passed -from that message. -input: xpos - the x-coordinate of the upper-left corner of the -client area of the window. -ypos - y-coordinate of the upper-left corner of the -client area of the window. -output: none -*******************************************************************/ -EXPORT void CALL MoveScreen (int xpos, int ypos) -{ - rdp.window_changed = TRUE; -} - -/****************************************************************** -Function: ResizeVideoOutput -Purpose: This function is called to force us to resize our output OpenGL window. - This is currently unsupported, and should never be called because we do - not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing. -input: new width and height -output: none -*******************************************************************/ -EXPORT void CALL ResizeVideoOutput(int Width, int Height) -{ -} - -/****************************************************************** -Function: RomClosed -Purpose: This function is called when a rom is closed. -input: none -output: none -*******************************************************************/ -EXPORT void CALL RomClosed (void) -{ - VLOG ("RomClosed ()\n"); - - CLOSE_RDP_LOG (); - CLOSE_RDP_E_LOG (); - rdp.window_changed = TRUE; - romopen = FALSE; - if (fullscreen && evoodoo) - ReleaseGfx (); -} - -static void CheckDRAMSize() -{ - wxUint32 test; - GLIDE64_TRY - { - test = gfx.RDRAM[0x007FFFFF] + 1; - } - GLIDE64_CATCH - { - test = 0; - } - if (test) - BMASK = 0x7FFFFF; - else - BMASK = WMASK; -#ifdef LOGGING - sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK); - LOG (out_buf); -#endif -} - -/****************************************************************** -Function: RomOpen -Purpose: This function is called when a rom is open. (from the -emulation thread) -input: none -output: none -*******************************************************************/ -EXPORT int CALL RomOpen (void) -{ - VLOG ("RomOpen ()\n"); - no_dlist = true; - romopen = TRUE; - ucode_error_report = TRUE; // allowed to report ucode errors - rdp_reset (); - - // Get the country code & translate to NTSC(0) or PAL(1) - wxUint16 code = ((wxUint16*)gfx.HEADER)[0x1F^1]; - - if (code == 0x4400) region = 1; // Germany (PAL) - if (code == 0x4500) region = 0; // USA (NTSC) - if (code == 0x4A00) region = 0; // Japan (NTSC) - if (code == 0x5000) region = 1; // Europe (PAL) - if (code == 0x5500) region = 0; // Australia (NTSC) - - char name[21] = "DEFAULT"; - ReadSpecialSettings (name); - - // get the name of the ROM - for (int i=0; i<20; i++) - name[i] = gfx.HEADER[(32+i)^3]; - name[20] = 0; - - // remove all trailing spaces - while (name[strlen(name)-1] == ' ') - name[strlen(name)-1] = 0; - - strncpy(rdp.RomName, name, sizeof(name)); - ReadSpecialSettings (name); - ClearCache (); - - CheckDRAMSize(); - - OPEN_RDP_LOG (); - OPEN_RDP_E_LOG (); - - - // ** EVOODOO EXTENSIONS ** - if (!fullscreen) - { - grGlideInit (); - grSstSelect (0); - } - const char *extensions = grGetString (GR_EXTENSION); - if (!fullscreen) - { - grGlideShutdown (); - - if (strstr (extensions, "EVOODOO")) - evoodoo = 1; - else - evoodoo = 0; - - if (evoodoo) - InitGfx (); - } - - if (strstr (extensions, "ROMNAME")) - { - char strSetRomName[] = "grSetRomName"; - void (FX_CALL *grSetRomName)(char*); - grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName); - grSetRomName (name); - } - // ** - return true; -} - -/****************************************************************** -Function: ShowCFB -Purpose: Useally once Dlists are started being displayed, cfb is -ignored. This function tells the dll to start displaying -them again. -input: none -output: none -*******************************************************************/ -bool no_dlist = true; -EXPORT void CALL ShowCFB (void) -{ - no_dlist = true; - VLOG ("ShowCFB ()\n"); -} - -EXPORT void CALL SetRenderingCallback(void (*callback)(int)) -{ - VLOG("CALL SetRenderingCallback (*)\n"); - renderCallback = callback; -} - -void drawViRegBG() -{ - LRDP("drawViRegBG\n"); - const wxUint32 VIwidth = *gfx.VI_WIDTH_REG; - FB_TO_SCREEN_INFO fb_info; - fb_info.width = VIwidth; - fb_info.height = (wxUint32)rdp.vi_height; - if (fb_info.height == 0) - { - LRDP("Image height = 0 - skipping\n"); - return; - } - fb_info.ul_x = 0; - - fb_info.lr_x = VIwidth - 1; - // fb_info.lr_x = (wxUint32)rdp.vi_width - 1; - fb_info.ul_y = 0; - fb_info.lr_y = fb_info.height - 1; - fb_info.opaque = 1; - fb_info.addr = *gfx.VI_ORIGIN_REG; - fb_info.size = *gfx.VI_STATUS_REG & 3; - rdp.last_bg = fb_info.addr; - - bool drawn = DrawFrameBufferToScreen(fb_info); - if (settings.hacks&hack_Lego && drawn) - { - rdp.updatescreen = 1; - newSwapBuffers (); - DrawFrameBufferToScreen(fb_info); - } -} - -} - -void drawNoFullscreenMessage(); - -void DrawFrameBuffer () -{ - if (!fullscreen) - { - drawNoFullscreenMessage(); - } - if (to_fullscreen) - GoToFullScreen(); - - if (fullscreen) - { - grDepthMask (FXTRUE); - grColorMask (FXTRUE, FXTRUE); - grBufferClear (0, 0, 0xFFFF); - drawViRegBG(); - } -} - -extern "C" { -/****************************************************************** -Function: UpdateScreen -Purpose: This function is called in response to a vsync of the -screen were the VI bit in MI_INTR_REG has already been -set -input: none -output: none -*******************************************************************/ -wxUint32 update_screen_count = 0; -EXPORT void CALL UpdateScreen (void) -{ -#ifdef LOG_KEY - if (CheckKeyPressed(G64_VK_SPACE, 0x0001)) - { - LOG ("KEY!!!\n"); - } -#endif - char out_buf[128]; - sprintf (out_buf, "UpdateScreen (). Origin: %08x, Old origin: %08x, width: %d\n", *gfx.VI_ORIGIN_REG, rdp.vi_org_reg, *gfx.VI_WIDTH_REG); - VLOG (out_buf); - LRDP(out_buf); - - wxUint32 width = (*gfx.VI_WIDTH_REG) << 1; - if (fullscreen && (*gfx.VI_ORIGIN_REG > width)) - update_screen_count++; -//TODO-PORT: wx times -#ifdef FPS - // vertical interrupt has occurred, increment counter - vi_count ++; - - // Check frames per second - LARGE_INTEGER difference; - QueryPerformanceCounter (&fps_next); - difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart; - float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart); - if (diff_secs > 0.5f) - { - fps = (float)(fps_count / diff_secs); - vi = (float)(vi_count / diff_secs); - ntsc_percent = vi / 0.6f; - pal_percent = vi / 0.5f; - fps_last = fps_next; - fps_count = 0; - vi_count = 0; - } -#endif - //* - wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30; - if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0)) - { - LRDP("DirectCPUWrite hack!\n"); - update_screen_count = 0; - no_dlist = true; - ClearCache (); - UpdateScreen(); - return; - } - //*/ - //* - if( no_dlist ) - { - if( *gfx.VI_ORIGIN_REG > width ) - { - ChangeSize (); - LRDP("ChangeSize done\n"); - DrawFrameBuffer(); - LRDP("DrawFrameBuffer done\n"); - rdp.updatescreen = 1; - newSwapBuffers (); - } - return; - } - //*/ - if (settings.swapmode == 0) - newSwapBuffers (); -} - -static void DrawWholeFrameBufferToScreen() -{ - static wxUint32 toScreenCI = 0; - if (rdp.ci_width < 200) - return; - if (rdp.cimg == toScreenCI) - return; - toScreenCI = rdp.cimg; - FB_TO_SCREEN_INFO fb_info; - fb_info.addr = rdp.cimg; - fb_info.size = rdp.ci_size; - fb_info.width = rdp.ci_width; - fb_info.height = rdp.ci_height; - if (fb_info.height == 0) - return; - fb_info.ul_x = 0; - fb_info.lr_x = rdp.ci_width-1; - fb_info.ul_y = 0; - fb_info.lr_y = rdp.ci_height-1; - fb_info.opaque = 0; - DrawFrameBufferToScreen(fb_info); - if (!(settings.frame_buffer & fb_ref)) - memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<>1); -} - -static void GetGammaTable() -{ - char strGetGammaTableExt[] = "grGetGammaTableExt"; - void (FX_CALL *grGetGammaTableExt)(FxU32, FxU32*, FxU32*, FxU32*) = - (void (FX_CALL *)(FxU32, FxU32*, FxU32*, FxU32*))grGetProcAddress(strGetGammaTableExt); - if (grGetGammaTableExt) - { - voodoo.gamma_table_r = new FxU32[voodoo.gamma_table_size]; - voodoo.gamma_table_g = new FxU32[voodoo.gamma_table_size]; - voodoo.gamma_table_b = new FxU32[voodoo.gamma_table_size]; - grGetGammaTableExt(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); - } -} - -} -wxUint32 curframe = 0; -void newSwapBuffers() -{ - if (!rdp.updatescreen) - return; - - rdp.updatescreen = 0; - - LRDP("swapped\n"); - - // Allow access to the whole screen - if (fullscreen) - { - rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; - grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); - grDepthBufferFunction (GR_CMP_ALWAYS); - grDepthMask (FXFALSE); - grCullMode (GR_CULL_DISABLE); - - if ((settings.show_fps & 0xF) || settings.clock) - set_message_combiner (); -#ifdef FPS - float y = (float)settings.res_y; - if (settings.show_fps & 0x0F) - { - if (settings.show_fps & 4) - { - if (region) // PAL - output (0, y, 0, "%d%% ", (int)pal_percent); - else - output (0, y, 0, "%d%% ", (int)ntsc_percent); - y -= 16; - } - if (settings.show_fps & 2) - { - output (0, y, 0, "VI/s: %.02f ", vi); - y -= 16; - } - if (settings.show_fps & 1) - output (0, y, 0, "FPS: %.02f ", fps); - } -#endif - - if (settings.clock) - { - if (settings.clock_24_hr) - { - time_t ltime; - time (<ime); - tm *cur_time = localtime (<ime); - - sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec); - } - else - { - char ampm[] = "AM"; - time_t ltime; - - time (<ime); - tm *cur_time = localtime (<ime); - - if (cur_time->tm_hour >= 12) - { - strcpy (ampm, "PM"); - if (cur_time->tm_hour != 12) - cur_time->tm_hour -= 12; - } - if (cur_time->tm_hour == 0) - cur_time->tm_hour = 12; - - if (cur_time->tm_hour >= 10) - sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm); - else - sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm); - } - output ((float)(settings.res_x - 68), y, 0, out_buf, 0); - } - //hotkeys - if (CheckKeyPressed(G64_VK_BACK, 0x0001)) - { - hotkey_info.hk_filtering = 100; - if (settings.filtering < 2) - settings.filtering++; - else - settings.filtering = 0; - } - if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000)) //alt + - { - if (CheckKeyPressed(G64_VK_B, 0x8000)) //b - { - hotkey_info.hk_motionblur = 100; - hotkey_info.hk_ref = 0; - curframe = frame_count; - settings.frame_buffer ^= fb_motionblur; - } - else if (CheckKeyPressed(G64_VK_V, 0x8000)) //v - { - hotkey_info.hk_ref = 100; - hotkey_info.hk_motionblur = 0; - curframe = frame_count; - settings.frame_buffer ^= fb_ref; - } - } - if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering)) - { - set_message_combiner (); - char buf[256]; - buf[0] = 0; - char * message = 0; - if (hotkey_info.hk_ref) - { - if (settings.frame_buffer & fb_ref) - message = strcat(buf, "FB READ ALWAYS: ON"); - else - message = strcat(buf, "FB READ ALWAYS: OFF"); - hotkey_info.hk_ref--; - } - if (hotkey_info.hk_motionblur) - { - if (settings.frame_buffer & fb_motionblur) - message = strcat(buf, " MOTION BLUR: ON"); - else - message = strcat(buf, " MOTION BLUR: OFF"); - hotkey_info.hk_motionblur--; - } - if (hotkey_info.hk_filtering) - { - switch (settings.filtering) - { - case 0: - message = strcat(buf, " FILTERING MODE: AUTOMATIC"); - break; - case 1: - message = strcat(buf, " FILTERING MODE: FORCE BILINEAR"); - break; - case 2: - message = strcat(buf, " FILTERING MODE: FORCE POINT-SAMPLED"); - break; - } - hotkey_info.hk_filtering--; - } - output (120.0f, (float)settings.res_y, 0, message, 0); - } - } - #ifdef OLDAPI - if (capture_screen) - { - //char path[256]; - // Make the directory if it doesn't exist - if (!wxDirExists(capture_path)) - wxMkdir(capture_path); - wxString path; - wxString romName = rdp.RomName; - romName.Replace(wxT(" "), wxT("_"), true); - romName.Replace(wxT(":"), wxT(";"), true); - - for (int i=1; ; i++) - { - path = capture_path; - path += wxT("Glide64mk2_"); - path += romName; - path += wxT("_"); - if (i < 10) - path += wxT("0"); - path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension; - if (!wxFileName::FileExists(path)) - break; - } - - const wxUint32 offset_x = (wxUint32)rdp.offset_x; - const wxUint32 offset_y = (wxUint32)rdp.offset_y; - const wxUint32 image_width = settings.scr_res_x - offset_x*2; - const wxUint32 image_height = settings.scr_res_y - offset_y*2; - - GrLfbInfo_t info; - info.size = sizeof(GrLfbInfo_t); - if (grLfbLock (GR_LFB_READ_ONLY, - GR_BUFFER_BACKBUFFER, - GR_LFBWRITEMODE_565, - GR_ORIGIN_UPPER_LEFT, - FXFALSE, - &info)) - { - wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor - int sspos = 0; - wxUint32 offset_src = info.strideInBytes * offset_y; - - // Copy the screen - if (info.writeMode == GR_LFBWRITEMODE_8888) - { - wxUint32 col; - for (wxUint32 y = 0; y < image_height; y++) - { - wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src); - ptr += offset_x; - for (wxUint32 x = 0; x < image_width; x++) - { - col = *(ptr++); - ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF); - ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF); - ssimg[sspos++] = (wxUint8)(col & 0xFF); - } - offset_src += info.strideInBytes; - } - } - else - { - wxUint16 col; - for (wxUint32 y = 0; y < image_height; y++) - { - wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src); - ptr += offset_x; - for (wxUint32 x = 0; x < image_width; x++) - { - col = *(ptr++); - ssimg[sspos++] = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f); - ssimg[sspos++] = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f); - ssimg[sspos++] = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f); - } - offset_src += info.strideInBytes; - } - } - // Unlock the backbuffer - grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER); - wxImage screenshot(image_width, image_height, ssimg); - screenshot.SaveFile(path, ScreenShotFormats[settings.ssformat].type); - capture_screen = 0; - } - } - #endif - - // Capture the screen if debug capture is set - if (_debugger.capture) - { - // Allocate the screen - _debugger.screen = new wxUint8 [(settings.res_x*settings.res_y) << 1]; - - // Lock the backbuffer (already rendered) - GrLfbInfo_t info; - info.size = sizeof(GrLfbInfo_t); - while (!grLfbLock (GR_LFB_READ_ONLY, - GR_BUFFER_BACKBUFFER, - GR_LFBWRITEMODE_565, - GR_ORIGIN_UPPER_LEFT, - FXFALSE, - &info)); - - wxUint32 offset_src=0, offset_dst=0; - - // Copy the screen - for (wxUint32 y=0; y> 19) & 0x1F); - g = (wxUint8)((col >> 10) & 0x3F); - b = (wxUint8)((col >> 3) & 0x1F); - dst[x] = (r<<11)|(g<<5)|b; - } - } - else - { - memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1); - } - offset_dst += settings.res_x << 1; - offset_src += info.strideInBytes; - } - - // Unlock the backbuffer - grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER); - } - - if (fullscreen && debugging) - { - debug_keys (); - debug_cacheviewer (); - debug_mouse (); - } - - if (settings.frame_buffer & fb_read_back_to_screen) - DrawWholeFrameBufferToScreen(); - - if (fullscreen) - { - if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo) - grAuxBufferExt( GR_BUFFER_AUXBUFFER ); - grBufferSwap (settings.vsync); - fps_count ++; - if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used - { - if (!voodoo.gamma_correction) - { - if (voodoo.gamma_table_size && !voodoo.gamma_table_r) - GetGammaTable(); //save initial gamma tables - guGammaCorrectionRGB(2.0f, 2.0f, 2.0f); //with gamma=2.0 gamma table is the same, as in N64 - voodoo.gamma_correction = 1; - } - } - else - { - if (voodoo.gamma_correction) - { - if (voodoo.gamma_table_r) - grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); - else - guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop - voodoo.gamma_correction = 0; - } - } - } - - if (_debugger.capture) - debug_capture (); - - if (fullscreen) - { - if (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6)) - { - if (settings.hacks&hack_RE2 && fb_depth_render_enabled) - grDepthMask (FXFALSE); - else - grDepthMask (FXTRUE); - grBufferClear (0, 0, 0xFFFF); - } - /* //let the game to clear the buffers - else - { - grDepthMask (FXTRUE); - grColorMask (FXFALSE, FXFALSE); - grBufferClear (0, 0, 0xFFFF); - grColorMask (FXTRUE, FXTRUE); - } - */ - } - - if (settings.frame_buffer & fb_read_back_to_screen2) - DrawWholeFrameBufferToScreen(); - - frame_count ++; - - // Open/close debugger? - if (CheckKeyPressed(G64_VK_SCROLL, 0x0001)) - { - if (!debugging) - { - //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768) - { - debugging = 1; - - // Recalculate screen size, don't resize screen - settings.res_x = (wxUint32)(settings.scr_res_x * 0.625f); - settings.res_y = (wxUint32)(settings.scr_res_y * 0.625f); - - ChangeSize (); - } - } - else - { - debugging = 0; - - settings.res_x = settings.scr_res_x; - settings.res_y = settings.scr_res_y; - - ChangeSize (); - } - } - - // Debug capture? - if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001)) - { - _debugger.capture = 1; - } -} - -extern "C" -{ - -/****************************************************************** -Function: ViStatusChanged -Purpose: This function is called to notify the dll that the -ViStatus registers value has been changed. -input: none -output: none -*******************************************************************/ -EXPORT void CALL ViStatusChanged (void) -{ -} - -/****************************************************************** -Function: ViWidthChanged -Purpose: This function is called to notify the dll that the -ViWidth registers value has been changed. -input: none -output: none -*******************************************************************/ -EXPORT void CALL ViWidthChanged (void) -{ -} - -#ifdef WINPROC_OVERRIDE -LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_ACTIVATEAPP: - if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE; - break; - case WM_PAINT: - if (!fullscreen) rdp.window_changed = TRUE; - break; - - /* case WM_DESTROY: - SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc); - break;*/ - } - - return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); -} -#endif - -} - -int CheckKeyPressed(int key, int mask) -{ -static Glide64Keys g64Keys; - if (settings.use_hotkeys == 0) - return 0; -#ifdef __WINDOWS__ - return (GetAsyncKeyState(g64Keys[key]) & mask); -#else - if (grKeyPressed) - return grKeyPressed(g64Keys[key]); -#endif - return 0; -} - - -#ifdef ALTTAB_FIX -int k_ctl=0, k_alt=0, k_del=0; - -LRESULT CALLBACK LowLevelKeyboardProc(int nCode, - WPARAM wParam, LPARAM lParam) -{ - if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam); - - int TabKey = FALSE; - - PKBDLLHOOKSTRUCT p; - - if (nCode == HC_ACTION) - { - switch (wParam) { -case WM_KEYUP: case WM_SYSKEYUP: - p = (PKBDLLHOOKSTRUCT) lParam; - if (p->vkCode == 162) k_ctl = 0; - if (p->vkCode == 164) k_alt = 0; - if (p->vkCode == 46) k_del = 0; - goto do_it; - -case WM_KEYDOWN: case WM_SYSKEYDOWN: - p = (PKBDLLHOOKSTRUCT) lParam; - if (p->vkCode == 162) k_ctl = 1; - if (p->vkCode == 164) k_alt = 1; - if (p->vkCode == 46) k_del = 1; - goto do_it; - -do_it: - TabKey = - ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) || - ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) || - ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) || - (k_ctl && k_alt && k_del); - - break; - } - } - - if (TabKey) - { - k_ctl = 0; - k_alt = 0; - k_del = 0; - ReleaseGfx (); - } - - return CallNextHookEx(NULL, nCode, wParam, lParam); -} -#endif - -// -// DllMain - called when the DLL is loaded, use this to get the DLL's instance -// -#ifdef OLDAPI -class wxDLLApp : public wxApp -{ -public: - virtual bool OnInit(); -}; - -IMPLEMENT_APP_NO_MAIN(wxDLLApp) - -bool wxDLLApp::OnInit() -{ - if (mutexProcessDList == NULL) - mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT); - wxImage::AddHandler(new wxPNGHandler); - wxImage::AddHandler(new wxJPEGHandler); - return true; -} - -#ifndef __WINDOWS__ -int __attribute__ ((constructor)) DllLoad(void); -int __attribute__ ((destructor)) DllUnload(void); -#endif - -// Called when the library is loaded and before dlopen() returns -int DllLoad(void) -{ - int argc = 0; - char **argv = NULL; - wxEntryStart(argc, argv); - if (wxTheApp) - return wxTheApp->CallOnInit() ? TRUE : FALSE; - return 0; -} - -// Called when the library is unloaded and before dlclose() returns -int DllUnload(void) -{ - if ( wxTheApp ) - wxTheApp->OnExit(); - wxEntryCleanup(); - return TRUE; -} - -#ifdef __WINDOWS__ -extern "C" int WINAPI DllMain (HINSTANCE hinstDLL, - wxUint32 fdwReason, - LPVOID lpReserved) -{ - sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason); - LOG (out_buf); - - if (fdwReason == DLL_PROCESS_ATTACH) - { - wxSetInstance(hinstDLL); - return DllLoad(); - } - else if (fdwReason == DLL_PROCESS_DETACH) - { - if (GFXWindow != NULL) - GFXWindow->SetHWND(NULL); - return DllUnload(); - } - return TRUE; -} - -void CALL ReadScreen(void **dest, int *width, int *height) -{ - *width = settings.res_x; - *height = settings.res_y; - wxUint8 * buff = (wxUint8*)malloc(settings.res_x * settings.res_y * 3); - wxUint8 * line = buff; - *dest = (void*)buff; - - if (!fullscreen) - { - for (wxUint32 y=0; y> 16) & 0xFF); - g = (wxUint8)((col >> 8) & 0xFF); - b = (wxUint8)(col & 0xFF); - line[x*3] = b; - line[x*3+1] = g; - line[x*3+2] = r; - } - line += settings.res_x * 3; - offset_src -= info.strideInBytes; - } - } - else - { - wxUint16 col; - for (wxUint32 y=0; y> 11) / 31.0f * 255.0f); - g = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f); - b = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f); - line[x*3] = b; - line[x*3+1] = g; - line[x*3+2] = r; - } - line += settings.res_x * 3; - offset_src -= info.strideInBytes; - } - } - // Unlock the frontbuffer - grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER); - } - LOG ("ReadScreen. Success.\n"); -} -#endif -#endif +/* +* Glide64 - Glide video plugin for Nintendo 64 emulators. +* Copyright (c) 2002 Dave2001 +* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski +* +* 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 +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//**************************************************************** +// +// Glide64 - Glide Plugin for Nintendo 64 emulators +// Project started on December 29th, 2001 +// +// Authors: +// Dave2001, original author, founded the project in 2001, left it in 2002 +// Gugaman, joined the project in 2002, left it in 2002 +// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 +// Hiroshi 'KoolSmoky' Morii, joined the project in 2007 +// +//**************************************************************** +// +// To modify Glide64: +// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. +// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. +// +//**************************************************************** + +#include "Gfx_1.3.h" +#include "Config.h" +#include "Util.h" +#include "3dmath.h" +#include "Debugger.h" +#include "Combine.h" +#include "TexCache.h" +#include "CRC.h" +#include "FBtoScreen.h" +#include "DepthBufferRender.h" + +#if defined(__GNUC__) +#include +#elif defined(__MSC__) +#include +#define PATH_MAX MAX_PATH +#endif +#include "osal_dynamiclib.h" +#ifdef TEXTURE_FILTER // Hiroshi Morii +#include +int ghq_dmptex_toggle_key = 0; +#endif +#if defined(__MINGW32__) +#define swprintf _snwprintf +#define vswprintf _vsnwprintf +#endif + +#define G64_VERSION "G64 Mk2" +#define RELTIME "Date: " __DATE__// " Time: " __TIME__ + +#ifdef EXT_LOGGING +std::ofstream extlog; +#endif + +#ifdef LOGGING +std::ofstream loga; +#endif + +#ifdef RDP_LOGGING +int log_open = FALSE; +std::ofstream rdp_log; +#endif + +#ifdef RDP_ERROR_LOG +int elog_open = FALSE; +std::ofstream rdp_err; +#endif + +GFX_INFO gfx; + +/* definitions of pointers to Core config functions */ +ptr_ConfigOpenSection ConfigOpenSection = NULL; +ptr_ConfigSetParameter ConfigSetParameter = NULL; +ptr_ConfigGetParameter ConfigGetParameter = NULL; +ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; +ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; +ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; +ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; +ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; +ptr_ConfigGetParamInt ConfigGetParamInt = NULL; +ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; +ptr_ConfigGetParamBool ConfigGetParamBool = NULL; +ptr_ConfigGetParamString ConfigGetParamString = NULL; + +ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; +ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; +ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; +ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; + +/* definitions of pointers to Core video extension functions */ +ptr_VidExt_Init CoreVideo_Init = NULL; +ptr_VidExt_Quit CoreVideo_Quit = NULL; +ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL; +ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; +ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; +ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; +ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; +ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL; +ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL; +ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL; +int to_fullscreen = FALSE; +int fullscreen = FALSE; +int romopen = FALSE; +GrContext_t gfx_context = 0; +int debugging = FALSE; +int exception = FALSE; + +int evoodoo = 0; +int ev_fullscreen = 0; + +enum { + NONE, + ASB, + BANJO2, + BAR, + CHOPPER, + DIDDY, + FIFA98, + FZERO, + GOLDENEYE, + HYPERBIKE, + ISS64, + KI, + KNOCKOUT, + LEGO, + MK64, + MEGAMAN, + MAKERS, + WCWNITRO, + OGRE64, + PILOTWINGS, + PMARIO, + PPL, + RE2, + STARCRAFT, + SUPERCROSS, + TGR, + TGR2, + TONIC, + YOSHI, + ZELDA +}; + +#ifdef __WINDOWS__ +#define WINPROC_OVERRIDE +#endif + +#ifdef WINPROC_OVERRIDE +LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +WNDPROC oldWndProc = NULL; +WNDPROC myWndProc = NULL; +#endif + +#ifdef ALTTAB_FIX +HHOOK hhkLowLevelKybd = NULL; +LRESULT CALLBACK LowLevelKeyboardProc(int nCode, + WPARAM wParam, LPARAM lParam); +#endif + +#ifdef PERFORMANCE +int64 perf_cur; +int64 perf_next; +#endif + +#ifdef FPS +LARGE_INTEGER perf_freq; +LARGE_INTEGER fps_last; +LARGE_INTEGER fps_next; +float fps = 0.0f; +wxUint32 fps_count = 0; + +wxUint32 vi_count = 0; +float vi = 0.0f; + +wxUint32 region = 0; + +float ntsc_percent = 0.0f; +float pal_percent = 0.0f; + +#endif + +// ref rate +// 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff + +unsigned long BMASK = 0x7FFFFF; +// Reality display processor structure +RDP rdp; + +SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 }; + +HOTKEY_INFO hotkey_info; + +VOODOO voodoo = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + +GrTexInfo fontTex; +GrTexInfo cursorTex; +wxUint32 offset_font = 0; +wxUint32 offset_cursor = 0; +wxUint32 offset_textures = 0; +wxUint32 offset_texbuf1 = 0; + +int capture_screen = 0; +char capture_path[256]; + +SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1); + +// SOME FUNCTION DEFINITIONS + +static void DrawFrameBuffer (); + + +void (*renderCallback)(int) = NULL; +static void (*l_DebugCallback)(void *, int, const char *) = NULL; +static void *l_DebugCallContext = NULL; + +void _ChangeSize () +{ + rdp.scale_1024 = settings.scr_res_x / 1024.0f; + rdp.scale_768 = settings.scr_res_y / 768.0f; + +// float res_scl_x = (float)settings.res_x / 320.0f; + float res_scl_y = (float)settings.res_y / 240.0f; + + wxUint32 scale_x = *gfx.VI_X_SCALE_REG & 0xFFF; + if (!scale_x) return; + wxUint32 scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF; + if (!scale_y) return; + + float fscale_x = (float)scale_x / 1024.0f; + float fscale_y = (float)scale_y / 2048.0f; + + wxUint32 dwHStartReg = *gfx.VI_H_START_REG; + wxUint32 dwVStartReg = *gfx.VI_V_START_REG; + + wxUint32 hstart = dwHStartReg >> 16; + wxUint32 hend = dwHStartReg & 0xFFFF; + + // dunno... but sometimes this happens + if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x); + + wxUint32 vstart = dwVStartReg >> 16; + wxUint32 vend = dwVStartReg & 0xFFFF; + + rdp.vi_width = (hend - hstart) * fscale_x; + rdp.vi_height = (vend - vstart) * fscale_y * 1.0126582f; + float aspect = (settings.adjust_aspect && (fscale_y > fscale_x) && (rdp.vi_width > rdp.vi_height)) ? fscale_x/fscale_y : 1.0f; + +#ifdef LOGGING + sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend); + LOG (out_buf); + sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height); + LOG (out_buf); +#endif + + rdp.scale_x = (float)settings.res_x / rdp.vi_width; + if (region > 0 && settings.pal230) + { + // odd... but pal games seem to want 230 as height... + rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height) * aspect; + } + else + { + rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect; + } + // rdp.offset_x = settings.offset_x * res_scl_x; + // rdp.offset_y = settings.offset_y * res_scl_y; + //rdp.offset_x = 0; + // rdp.offset_y = 0; + rdp.offset_y = ((float)settings.res_y - rdp.vi_height * rdp.scale_y) * 0.5f; + if (((wxUint32)rdp.vi_width <= (*gfx.VI_WIDTH_REG)/2) && (rdp.vi_width > rdp.vi_height)) + rdp.scale_y *= 0.5f; + + rdp.scissor_o.ul_x = 0; + rdp.scissor_o.ul_y = 0; + rdp.scissor_o.lr_x = (wxUint32)rdp.vi_width; + rdp.scissor_o.lr_y = (wxUint32)rdp.vi_height; + + rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; +} + +void ChangeSize () +{ + if (debugging) + { + _ChangeSize (); + return; + } + switch (settings.aspectmode) + { + case 0: //4:3 + if (settings.scr_res_x >= settings.scr_res_y * 4.0f / 3.0f) { + settings.res_y = settings.scr_res_y; + settings.res_x = (wxUint32)(settings.res_y * 4.0f / 3.0f); + } else { + settings.res_x = settings.scr_res_x; + settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f); + } + break; + case 1: //16:9 + if (settings.scr_res_x >= settings.scr_res_y * 16.0f / 9.0f) { + settings.res_y = settings.scr_res_y; + settings.res_x = (wxUint32)(settings.res_y * 16.0f / 9.0f); + } else { + settings.res_x = settings.scr_res_x; + settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f); + } + break; + default: //stretch or original + settings.res_x = settings.scr_res_x; + settings.res_y = settings.scr_res_y; + } + _ChangeSize (); + rdp.offset_x = (settings.scr_res_x - settings.res_x) / 2.0f; + float offset_y = (settings.scr_res_y - settings.res_y) / 2.0f; + settings.res_x += (wxUint32)rdp.offset_x; + settings.res_y += (wxUint32)offset_y; + rdp.offset_y += offset_y; + if (settings.aspectmode == 3) // original + { + rdp.scale_x = rdp.scale_y = 1.0f; + rdp.offset_x = (settings.scr_res_x - rdp.vi_width) / 2.0f; + rdp.offset_y = (settings.scr_res_y - rdp.vi_height) / 2.0f; + } + // settings.res_x = settings.scr_res_x; + // settings.res_y = settings.scr_res_y; +} + +void ConfigWrapper() +{ + char strConfigWrapperExt[] = "grConfigWrapperExt"; + GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt); + if (grConfigWrapperExt) + grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic); +} +/* +static wxConfigBase * OpenIni() +{ + wxConfigBase * ini = wxConfigBase::Get(false); + if (!ini) + { + if (iniName.IsEmpty()) + iniName = pluginPath + wxT("/Glide64mk2.ini"); + if (wxFileExists(iniName)) + { + wxFileInputStream is(iniName); + wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1); + wxConfigBase::Set(fcfg); + ini = fcfg; + } + } + if (!ini) + wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION); + return ini; +} +*/ +#ifndef OLDAPI +void WriteLog(m64p_msg_level level, const char *msg, ...) +{ + char buf[1024]; + va_list args; + va_start(args, msg); + vsnprintf(buf, 1023, msg, args); + buf[1023]='\0'; + va_end(args); + if (l_DebugCallback) + { + l_DebugCallback(l_DebugCallContext, level, buf); + } +} +#endif + +void ReadSettings () +{ + // LOG("ReadSettings\n"); + if (!Config_Open()) + { + ERRLOG("Could not open configuration!"); + return; + } + + settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE); + //settings.lang_id not needed + // depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE); + settings.res_data = 0; + settings.scr_res_x = settings.res_x = Config_ReadScreenInt("ScreenWidth"); + settings.scr_res_y = settings.res_y = Config_ReadScreenInt("ScreenHeight"); + + settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0); + settings.ssformat = (BOOL)Config_ReadInt("ssformat", "TODO:ssformat", 0); + //settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0); + + settings.show_fps = (BYTE)Config_ReadInt ("show_fps", "Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent", 0, TRUE, FALSE); + settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0); + settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0); + // settings.advanced_options only good for GUI config + // settings.texenh_options = only good for GUI config + //settings.use_hotkeys = ini->Read(_T("hotkeys"), 1l); + + settings.wrpResolution = (BYTE)Config_ReadInt ("wrpResolution", "Wrapper resolution", 0, TRUE, FALSE); + settings.wrpVRAM = (BYTE)Config_ReadInt ("wrpVRAM", "Wrapper VRAM", 0, TRUE, FALSE); + settings.wrpFBO = (BOOL)Config_ReadInt ("wrpFBO", "Wrapper FBO", 1, TRUE, TRUE); + settings.wrpAnisotropic = (BOOL)Config_ReadInt ("wrpAnisotropic", "Wrapper Anisotropic Filtering", 0, TRUE, TRUE); + +#ifndef _ENDUSER_RELEASE_ + settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1); + settings.ucode = (wxUint32)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE); + settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0); + settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE); + + settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0); + settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0); + + settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0); + + settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0); + settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0); + settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0); + settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0); + settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0); +#else + settings.autodetect_ucode = TRUE; + settings.ucode = 2; + settings.wireframe = FALSE; + settings.wfmode = 0; + settings.logging = FALSE; + settings.log_clear = FALSE; + settings.run_in_window = FALSE; + settings.elogging = FALSE; + settings.filter_cache = FALSE; + settings.unk_as_red = FALSE; + settings.log_unk = FALSE; + settings.unk_clear = FALSE; +#endif + +#ifdef TEXTURE_FILTER + + // settings.ghq_fltr range is 0 through 6 + // Filters:\nApply a filter to either smooth or sharpen textures.\nThere are 4 different smoothing filters and 2 different sharpening filters.\nThe higher the number, the stronger the effect,\ni.e. \"Smoothing filter 4\" will have a much more noticeable effect than \"Smoothing filter 1\".\nBe aware that performance may have an impact depending on the game and/or the PC.\n[Recommended: your preference] + // _("None"), + // _("Smooth filtering 1"), + // _("Smooth filtering 2"), + // _("Smooth filtering 3"), + // _("Smooth filtering 4"), + // _("Sharp filtering 1"), + // _("Sharp filtering 2") + +// settings.ghq_cmpr 0=S3TC and 1=FXT1 + +//settings.ghq_ent is ___ +// "Texture enhancement:\n7 different filters are selectable here, each one with a distinctive look.\nBe aware of possible performance impacts.\n\nIMPORTANT: 'Store' mode - saves textures in cache 'as is'. It can improve performance in games, which load many textures.\nDisable 'Ignore backgrounds' option for better result.\n\n[Recommended: your preference]" + + + + settings.ghq_fltr = Config_ReadInt ("ghq_fltr", "Texture Enhancement: Smooth/Sharpen Filters", 0, TRUE, FALSE); + settings.ghq_cmpr = Config_ReadInt ("ghq_cmpr", "Texture Compression: 0 for S3TC, 1 for FXT1", 0, TRUE, FALSE); + settings.ghq_enht = Config_ReadInt ("ghq_enht", "Texture Enhancement: More filters", 0, TRUE, FALSE); + settings.ghq_hirs = Config_ReadInt ("ghq_hirs", "Hi-res texture pack format (0 for none, 1 for Rice)", 0, TRUE, FALSE); + settings.ghq_enht_cmpr = Config_ReadInt ("ghq_enht_cmpr", "Compress texture cache with S3TC or FXT1", 0, TRUE, TRUE); + settings.ghq_enht_tile = Config_ReadInt ("ghq_enht_tile", "Tile textures (saves memory but could cause issues)", 0, TRUE, FALSE); + settings.ghq_enht_f16bpp = Config_ReadInt ("ghq_enht_f16bpp", "Force 16bpp textures (saves ram but lower quality)", 0, TRUE, TRUE); + settings.ghq_enht_gz = Config_ReadInt ("ghq_enht_gz", "Compress texture cache", 1, TRUE, TRUE); + settings.ghq_enht_nobg = Config_ReadInt ("ghq_enht_nobg", "Don't enhance textures for backgrounds", 0, TRUE, TRUE); + settings.ghq_hirs_cmpr = Config_ReadInt ("ghq_hirs_cmpr", "Enable S3TC and FXT1 compression", 0, TRUE, TRUE); + settings.ghq_hirs_tile = Config_ReadInt ("ghq_hirs_tile", "Tile hi-res textures (saves memory but could cause issues)", 0, TRUE, TRUE); + settings.ghq_hirs_f16bpp = Config_ReadInt ("ghq_hirs_f16bpp", "Force 16bpp hi-res textures (saves ram but lower quality)", 0, TRUE, TRUE); + settings.ghq_hirs_gz = Config_ReadInt ("ghq_hirs_gz", "Compress hi-res texture cache", 1, TRUE, TRUE); + settings.ghq_hirs_altcrc = Config_ReadInt ("ghq_hirs_altcrc", "Alternative CRC calculation -- emulates Rice bug", 1, TRUE, TRUE); + settings.ghq_cache_save = Config_ReadInt ("ghq_cache_save", "Save tex cache to disk", 1, TRUE, TRUE); + settings.ghq_cache_size = Config_ReadInt ("ghq_cache_size", "Texture Cache Size (MB)", 128, TRUE, FALSE); + settings.ghq_hirs_let_texartists_fly = Config_ReadInt ("ghq_hirs_let_texartists_fly", "Use full alpha channel -- could cause issues for some tex packs", 0, TRUE, TRUE); + settings.ghq_hirs_dump = Config_ReadInt ("ghq_hirs_dump", "Dump textures", 0, FALSE, TRUE); +#endif + //TODO-PORT: remove? + ConfigWrapper(); +} + +void ReadSpecialSettings (const char * name) +{ + // char buf [256]; + // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name); + // LOG(buf); + + int EnableHacksForGame = (int)Config_ReadInt ("enable_hacks_for_game", "???", 0, TRUE, FALSE); + + switch (EnableHacksForGame) + { + case NONE: + break; + case ASB: + settings.hacks |= hack_ASB; + break; + case BANJO2: + settings.hacks |= hack_Banjo2; + break; + case BAR: + settings.hacks |= hack_BAR; + break; + case CHOPPER: + settings.hacks |= hack_Chopper; + break; + case DIDDY: + settings.hacks |= hack_Diddy; + break; + case FIFA98: + settings.hacks |= hack_Fifa98; + break; + case FZERO: + settings.hacks |= hack_Fzero; + break; + case GOLDENEYE: + settings.hacks |= hack_GoldenEye; + break; + case HYPERBIKE: + settings.hacks |= hack_Hyperbike; + break; + case ISS64: + settings.hacks |= hack_ISS64; + break; + case KI: + settings.hacks |= hack_KI; + break; + case KNOCKOUT: + settings.hacks |= hack_Knockout; + break; + case LEGO: + settings.hacks |= hack_Lego; + break; + case MK64: + settings.hacks |= hack_MK64; + break; + case MEGAMAN: + settings.hacks |= hack_Megaman; + break; + case MAKERS: + settings.hacks |= hack_Makers; + break; + case WCWNITRO: + settings.hacks |= hack_WCWnitro; + break; + case OGRE64: + settings.hacks |= hack_Ogre64; + break; + case PILOTWINGS: + settings.hacks |= hack_Pilotwings; + break; + case PMARIO: + settings.hacks |= hack_PMario; + break; + case PPL: + settings.hacks |= hack_PPL; + break; + case RE2: + settings.hacks |= hack_RE2; + break; + case STARCRAFT: + settings.hacks |= hack_Starcraft; + break; + case SUPERCROSS: + settings.hacks |= hack_Supercross; + break; + case TGR: + settings.hacks |= hack_TGR; + break; + case TGR2: + settings.hacks |= hack_TGR2; + break; + case TONIC: + settings.hacks |= hack_Tonic; + break; + case YOSHI: + settings.hacks |= hack_Yoshi; + break; + case ZELDA: + settings.hacks |= hack_Zelda; + break; + } + + settings.alt_tex_size = (BOOL)Config_ReadInt("alt_tex_size", "???", TRUE); + settings.use_sts1_only = (BOOL)Config_ReadInt("use_sts1_only", "???", FALSE); + settings.force_calc_sphere = (BOOL)Config_ReadInt("force_calc_sphere", "???", FALSE); + settings.correct_viewport = (BOOL)Config_ReadInt("correct_viewport", "???", FALSE); + settings.increase_texrect_edge = (BOOL)Config_ReadInt("increase_texrect_edge", "???", FALSE); + settings.decrease_fillrect_edge = (BOOL)Config_ReadInt("decrease_fillrect_edge", "???", FALSE); + settings.texture_correction = (BOOL)Config_ReadInt("texture_correction", "???", TRUE); + + settings.force_microcheck = (BOOL)Config_ReadInt("force_microcheck", "???", FALSE); + settings.fog = (BOOL)Config_ReadInt("fog", "???", TRUE); + settings.buff_clear = (BOOL)Config_ReadInt("buff_clear", "???", TRUE); + settings.swapmode = (int)Config_ReadInt("swapmode", "???", 1, TRUE, FALSE); + int stipple_pattern = (int)Config_ReadInt("stipple_pattern", "???", 1041204192, TRUE, FALSE); + if (stipple_pattern > 0) settings.stipple_pattern = (wxUint32)stipple_pattern; + settings.stipple_mode = (int)Config_ReadInt("stipple_mode", "???", 2, TRUE, FALSE); + settings.lodmode = (int)Config_ReadInt("lodmode", "???", 0, TRUE, FALSE); + settings.filtering = (int)Config_ReadInt("filtering", "???", 0, TRUE, FALSE); + settings.pal230 = (BOOL)Config_ReadInt("pal230", "???", FALSE); + settings.texture_correction = (BOOL)Config_ReadInt("texture_correction", "???", TRUE); + settings.n64_z_scale = (BOOL)Config_ReadInt("n64_z_scale", "???", FALSE); + settings.old_style_adither = (BOOL)Config_ReadInt("old_style_adither", "???", FALSE); + settings.zmode_compare_less = (BOOL)Config_ReadInt("zmode_compare_less", "???", FALSE); + settings.adjust_aspect = (BOOL)Config_ReadInt("adjust_aspect", "???", TRUE); + settings.clip_zmax = (BOOL)Config_ReadInt("clip_zmax", "???", TRUE); + settings.clip_zmin = (BOOL)Config_ReadInt("clip_zmin", "???", FALSE); + settings.force_quad3d = (BOOL)Config_ReadInt("force_quad3d", "???", FALSE); + settings.aspectmode = (int)Config_ReadInt("aspectmode", "???", 0, TRUE, FALSE); + settings.fast_crc = (BOOL)Config_ReadInt("fast_crc", "???", TRUE); + + if (settings.n64_z_scale) + ZLUT_init(); + + //frame buffer + int optimize_texrect = (BOOL)Config_ReadInt("optimize_texrect", "???", TRUE); + int ignore_aux_copy = (BOOL)Config_ReadInt("ignore_aux_copy", "???", FALSE); + int hires_buf_clear = (BOOL)Config_ReadInt("hires_buf_clear", "???", TRUE); + int read_alpha = (BOOL)Config_ReadInt("fb_read_alpha", "???", FALSE); + int useless_is_useless = (BOOL)Config_ReadInt("useless_is_useless", "???", FALSE); + int fb_crc_mode = (int)Config_ReadInt("fb_crc_mode", "???", 1, TRUE, FALSE); + + if (optimize_texrect > 0) settings.frame_buffer |= fb_optimize_texrect; + else if (optimize_texrect == 0) settings.frame_buffer &= ~fb_optimize_texrect; + if (ignore_aux_copy > 0) settings.frame_buffer |= fb_ignore_aux_copy; + else if (ignore_aux_copy == 0) settings.frame_buffer &= ~fb_ignore_aux_copy; + if (hires_buf_clear > 0) settings.frame_buffer |= fb_hwfbe_buf_clear; + else if (hires_buf_clear == 0) settings.frame_buffer &= ~fb_hwfbe_buf_clear; + if (read_alpha > 0) settings.frame_buffer |= fb_read_alpha; + else if (read_alpha == 0) settings.frame_buffer &= ~fb_read_alpha; + if (useless_is_useless > 0) settings.frame_buffer |= fb_useless_is_useless; + else settings.frame_buffer &= ~fb_useless_is_useless; + if (fb_crc_mode >= 0) settings.fb_crc_mode = (SETTINGS::FBCRCMODE)fb_crc_mode; + + //frame buffer + int smart_read = (BOOL)Config_ReadInt("fb_smart", "???", FALSE); + int hires = (BOOL)Config_ReadInt("fb_hires", "???", TRUE); + int read_always = (BOOL)Config_ReadInt("fb_read_always", "???", FALSE); + int read_back_to_screen = (int)Config_ReadInt("read_back_to_screen", "???", 0, TRUE, FALSE); + int cpu_write_hack = (BOOL)Config_ReadInt("detect_cpu_write", "???", FALSE); + int get_fbinfo = (BOOL)Config_ReadInt("fb_get_info", "???", FALSE); + int depth_render = (BOOL)Config_ReadInt("fb_render", "???", TRUE); + + if (smart_read > 0) settings.frame_buffer |= fb_emulation; + else if (smart_read == 0) settings.frame_buffer &= ~fb_emulation; + if (hires > 0) settings.frame_buffer |= fb_hwfbe; + else if (hires == 0) settings.frame_buffer &= ~fb_hwfbe; + if (read_always > 0) settings.frame_buffer |= fb_ref; + else if (read_always == 0) settings.frame_buffer &= ~fb_ref; + if (read_back_to_screen == 1) settings.frame_buffer |= fb_read_back_to_screen; + else if (read_back_to_screen == 2) settings.frame_buffer |= fb_read_back_to_screen2; + else if (read_back_to_screen == 0) settings.frame_buffer &= ~(fb_read_back_to_screen|fb_read_back_to_screen2); + if (cpu_write_hack > 0) settings.frame_buffer |= fb_cpu_write_hack; + else if (cpu_write_hack == 0) settings.frame_buffer &= ~fb_cpu_write_hack; + if (get_fbinfo > 0) settings.frame_buffer |= fb_get_info; + else if (get_fbinfo == 0) settings.frame_buffer &= ~fb_get_info; + if (depth_render > 0) settings.frame_buffer |= fb_depth_render; + else if (depth_render == 0) settings.frame_buffer &= ~fb_depth_render; + settings.frame_buffer |= fb_motionblur; + + settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled; +} + +//TODO-PORT: more ini stuff +void WriteSettings (bool saveEmulationSettings) +{ +/* + wxConfigBase * ini = OpenIni(); + if (!ini || !ini->HasGroup(_T("/SETTINGS"))) + return; + ini->SetPath(_T("/SETTINGS")); + + ini->Write(_T("card_id"), settings.card_id); + ini->Write(_T("lang_id"), settings.lang_id); + ini->Write(_T("resolution"), (int)settings.res_data); + ini->Write(_T("ssformat"), settings.ssformat); + ini->Write(_T("vsync"), settings.vsync); + ini->Write(_T("show_fps"), settings.show_fps); + ini->Write(_T("clock"), settings.clock); + ini->Write(_T("clock_24_hr"), settings.clock_24_hr); + ini->Write(_T("advanced_options"), settings.advanced_options); + ini->Write(_T("texenh_options"), settings.texenh_options); + + ini->Write(_T("wrpResolution"), settings.wrpResolution); + ini->Write(_T("wrpVRAM"), settings.wrpVRAM); + ini->Write(_T("wrpFBO"), settings.wrpFBO); + ini->Write(_T("wrpAnisotropic"), settings.wrpAnisotropic); + +#ifndef _ENDUSER_RELEASE_ + ini->Write(_T("autodetect_ucode"), settings.autodetect_ucode); + ini->Write(_T("ucode"), (int)settings.ucode); + ini->Write(_T("wireframe"), settings.wireframe); + ini->Write(_T("wfmode"), settings.wfmode); + ini->Write(_T("logging"), settings.logging); + ini->Write(_T("log_clear"), settings.log_clear); + ini->Write(_T("run_in_window"), settings.run_in_window); + ini->Write(_T("elogging"), settings.elogging); + ini->Write(_T("filter_cache"), settings.filter_cache); + ini->Write(_T("unk_as_red"), settings.unk_as_red); + ini->Write(_T("log_unk"), settings.log_unk); + ini->Write(_T("unk_clear"), settings.unk_clear); +#endif //_ENDUSER_RELEASE_ + +#ifdef TEXTURE_FILTER + ini->Write(_T("ghq_fltr"), settings.ghq_fltr); + ini->Write(_T("ghq_cmpr"), settings.ghq_cmpr); + ini->Write(_T("ghq_enht"), settings.ghq_enht); + ini->Write(_T("ghq_hirs"), settings.ghq_hirs); + ini->Write(_T("ghq_enht_cmpr"), settings.ghq_enht_cmpr); + ini->Write(_T("ghq_enht_tile"), settings.ghq_enht_tile); + ini->Write(_T("ghq_enht_f16bpp"), settings.ghq_enht_f16bpp); + ini->Write(_T("ghq_enht_gz"), settings.ghq_enht_gz); + ini->Write(_T("ghq_enht_nobg"), settings.ghq_enht_nobg); + ini->Write(_T("ghq_hirs_cmpr"), settings.ghq_hirs_cmpr); + ini->Write(_T("ghq_hirs_tile"), settings.ghq_hirs_tile); + ini->Write(_T("ghq_hirs_f16bpp"), settings.ghq_hirs_f16bpp); + ini->Write(_T("ghq_hirs_gz"), settings.ghq_hirs_gz); + ini->Write(_T("ghq_hirs_altcrc"), settings.ghq_hirs_altcrc); + ini->Write(_T("ghq_cache_save"), settings.ghq_cache_save); + ini->Write(_T("ghq_cache_size"), settings.ghq_cache_size); + ini->Write(_T("ghq_hirs_let_texartists_fly"), settings.ghq_hirs_let_texartists_fly); + ini->Write(_T("ghq_hirs_dump"), settings.ghq_hirs_dump); +#endif + + if (saveEmulationSettings) + { + if (romopen) + { + wxString S = _T("/"); + ini->SetPath(S+rdp.RomName); + } + else + ini->SetPath(_T("/DEFAULT")); + ini->Write(_T("filtering"), settings.filtering); + ini->Write(_T("fog"), settings.fog); + ini->Write(_T("buff_clear"), settings.buff_clear); + ini->Write(_T("swapmode"), settings.swapmode); + ini->Write(_T("lodmode"), settings.lodmode); + ini->Write(_T("aspect"), settings.aspectmode); + + ini->Write(_T("fb_read_always"), settings.frame_buffer&fb_ref ? 1 : 0l); + ini->Write(_T("fb_smart"), settings.frame_buffer & fb_emulation ? 1 : 0l); + // ini->Write("motionblur", settings.frame_buffer & fb_motionblur ? 1 : 0); + ini->Write(_T("fb_hires"), settings.frame_buffer & fb_hwfbe ? 1 : 0l); + ini->Write(_T("fb_get_info"), settings.frame_buffer & fb_get_info ? 1 : 0l); + ini->Write(_T("fb_render"), settings.frame_buffer & fb_depth_render ? 1 : 0l); + ini->Write(_T("detect_cpu_write"), settings.frame_buffer & fb_cpu_write_hack ? 1 : 0l); + if (settings.frame_buffer & fb_read_back_to_screen) + ini->Write(_T("read_back_to_screen"), 1); + else if (settings.frame_buffer & fb_read_back_to_screen2) + ini->Write(_T("read_back_to_screen"), 2); + else + ini->Write(_T("read_back_to_screen"), 0l); + } + + wxFileOutputStream os(iniName); + ((wxFileConfig*)ini)->Save(os); +*/ +} + +GRTEXBUFFEREXT grTextureBufferExt = NULL; +GRTEXBUFFEREXT grTextureAuxBufferExt = NULL; +GRAUXBUFFEREXT grAuxBufferExt = NULL; +GRSTIPPLE grStippleModeExt = NULL; +GRSTIPPLE grStipplePatternExt = NULL; +FxBool (FX_CALL *grKeyPressed)(FxU32) = NULL; + +int GetTexAddrUMA(int tmu, int texsize) +{ + int addr = voodoo.tex_min_addr[0] + voodoo.tmem_ptr[0]; + voodoo.tmem_ptr[0] += texsize; + voodoo.tmem_ptr[1] = voodoo.tmem_ptr[0]; + return addr; +} +int GetTexAddrNonUMA(int tmu, int texsize) +{ + int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu]; + voodoo.tmem_ptr[tmu] += texsize; + return addr; +} +GETTEXADDR GetTexAddr = GetTexAddrNonUMA; + +// guLoadTextures - used to load the cursor and font textures +void guLoadTextures () +{ + if (grTextureBufferExt) + { + int tbuf_size = 0; + if (voodoo.max_tex_size <= 256) + { + grTextureBufferExt( GR_TMU1, voodoo.tex_min_addr[GR_TMU1], GR_LOD_LOG2_256, GR_LOD_LOG2_256, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); + tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); + } + else if (settings.scr_res_x <= 1024) + { + grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); + tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); + grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); + grBufferClear (0, 0, 0xFFFF); + grRenderBuffer( GR_BUFFER_BACKBUFFER ); + } + else + { + grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); + tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); + grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); + grBufferClear (0, 0, 0xFFFF); + grRenderBuffer( GR_BUFFER_BACKBUFFER ); + } + + rdp.texbufs[0].tmu = GR_TMU0; + rdp.texbufs[0].begin = voodoo.tex_min_addr[GR_TMU0]; + rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size; + rdp.texbufs[0].count = 0; + rdp.texbufs[0].clear_allowed = TRUE; + offset_font = tbuf_size; + if (voodoo.num_tmu > 1) + { + rdp.texbufs[1].tmu = GR_TMU1; + rdp.texbufs[1].begin = voodoo.tex_UMA ? rdp.texbufs[0].end : voodoo.tex_min_addr[GR_TMU1]; + rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size; + rdp.texbufs[1].count = 0; + rdp.texbufs[1].clear_allowed = TRUE; + if (voodoo.tex_UMA) + offset_font += tbuf_size; + else + offset_texbuf1 = tbuf_size; + } + } + else + offset_font = 0; + +#include "font.h" + wxUint32 *data = (wxUint32*)font; + wxUint32 cur; + + // ** Font texture ** + wxUint8 *tex8 = (wxUint8*)malloc(256*64); + + fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256; + fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1; + fontTex.format = GR_TEXFMT_ALPHA_8; + fontTex.data = tex8; + + // Decompression: [1-bit inverse alpha --> 8-bit alpha] + wxUint32 i,b; + for (i=0; i<0x200; i++) + { + // cur = ~*(data++), byteswapped +#ifdef __VISUALC__ + cur = _byteswap_ulong(~*(data++)); +#else + cur = ~*(data++); + cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF); +#endif + + for (b=0x80000000; b!=0; b>>=1) + { + if (cur&b) *tex8 = 0xFF; + else *tex8 = 0x00; + tex8 ++; + } + } + + grTexDownloadMipMap (GR_TMU0, + voodoo.tex_min_addr[GR_TMU0] + offset_font, + GR_MIPMAPLEVELMASK_BOTH, + &fontTex); + + offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex); + + free (fontTex.data); + + // ** Cursor texture ** +#include "cursor.h" + data = (wxUint32*)cursor; + + wxUint16 *tex16 = (wxUint16*)malloc(32*32*2); + + cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32; + cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; + cursorTex.format = GR_TEXFMT_ARGB_1555; + cursorTex.data = tex16; + + // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555] + for (i=0; i<0x200; i++) + { + cur = *(data++); + *(tex16++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8)); + *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24)); + } + + grTexDownloadMipMap (GR_TMU0, + voodoo.tex_min_addr[GR_TMU0] + offset_cursor, + GR_MIPMAPLEVELMASK_BOTH, + &cursorTex); + + // Round to higher 16 + offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex)) + & 0xFFFFFFF0) + 16; + free (cursorTex.data); +} + +#ifdef TEXTURE_FILTER +void DisplayLoadProgress(const wchar_t *format, ...) +{ + va_list args; + wchar_t wbuf[INFO_BUF]; + char buf[INFO_BUF]; + + // process input + va_start(args, format); + vswprintf(wbuf, INFO_BUF, format, args); + va_end(args); + + // XXX: convert to multibyte + wcstombs(buf, wbuf, INFO_BUF); + + if (fullscreen) + { + float x; + set_message_combiner (); + output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT..."); + int len = min (strlen(buf)*8, 1024); + x = (1024-len)/2.0f; + output (x, 360, 1, buf); + grBufferSwap (0); + grColorMask (FXTRUE, FXTRUE); + grBufferClear (0, 0, 0xFFFF); + } +} +#endif + +int InitGfx () +{ +#ifdef TEXTURE_FILTER + wchar_t romname[256]; + wchar_t foldername[PATH_MAX + 64]; + wchar_t cachename[PATH_MAX + 64]; +#endif + if (fullscreen) + ReleaseGfx (); + + OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it + OPEN_RDP_E_LOG (); + VLOG ("InitGfx ()\n"); + + debugging = FALSE; + rdp_reset (); + + // Initialize Glide + grGlideInit (); + + // Select the Glide device + grSstSelect (settings.card_id); + + // Is mirroring allowed? + const char *extensions = grGetString (GR_EXTENSION); + + // Check which SST we are using and initialize stuff + // Hiroshi Morii + enum { + GR_SSTTYPE_VOODOO = 0, + GR_SSTTYPE_SST96 = 1, + GR_SSTTYPE_AT3D = 2, + GR_SSTTYPE_Voodoo2 = 3, + GR_SSTTYPE_Banshee = 4, + GR_SSTTYPE_Voodoo3 = 5, + GR_SSTTYPE_Voodoo4 = 6, + GR_SSTTYPE_Voodoo5 = 7 + }; + const char *hardware = grGetString(GR_HARDWARE); + unsigned int SST_type = GR_SSTTYPE_VOODOO; + if (strstr(hardware, "Rush")) { + SST_type = GR_SSTTYPE_SST96; + } else if (strstr(hardware, "Voodoo2")) { + SST_type = GR_SSTTYPE_Voodoo2; + } else if (strstr(hardware, "Voodoo Banshee")) { + SST_type = GR_SSTTYPE_Banshee; + } else if (strstr(hardware, "Voodoo3")) { + SST_type = GR_SSTTYPE_Voodoo3; + } else if (strstr(hardware, "Voodoo4")) { + SST_type = GR_SSTTYPE_Voodoo4; + } else if (strstr(hardware, "Voodoo5")) { + SST_type = GR_SSTTYPE_Voodoo5; + } + // 2Mb Texture boundary + voodoo.has_2mb_tex_boundary = (SST_type < GR_SSTTYPE_Banshee) && !evoodoo; + // use UMA if available + voodoo.tex_UMA = FALSE; + //* + if (strstr(extensions, " TEXUMA ")) { + // we get better texture cache hits with UMA on + grEnable(GR_TEXTURE_UMA_EXT); + voodoo.tex_UMA = TRUE; + LOG ("Using TEXUMA extension.\n"); + } + //*/ +//TODO-PORT: fullscreen stuff + wxUint32 res_data = settings.res_data; + char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt"; + if (ev_fullscreen) + { + GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt = + (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt); + if (grWrapperFullScreenResolutionExt) { + wxUint32 _width, _height = 0; + settings.res_data = grWrapperFullScreenResolutionExt(&_width, &_height); + settings.scr_res_x = settings.res_x = _width; + settings.scr_res_y = settings.res_y = _height; + } + res_data = settings.res_data; + } + else if (evoodoo) + { + GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt = + (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt); + if (grWrapperFullScreenResolutionExt != NULL) + { +/* + TODO-port: fix resolutions + settings.res_data = settings.res_data_org; + settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0]; + settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1]; +*/ + } + res_data = settings.res_data | 0x80000000; + } + + gfx_context = 0; + + // Select the window + + if (fb_hwfbe_enabled) + { + char strSstWinOpenExt[] ="grSstWinOpenExt"; + GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt); + if (grSstWinOpenExt) + gfx_context = grSstWinOpenExt ((FxU32)NULL, + res_data, + GR_REFRESH_60Hz, + GR_COLORFORMAT_RGBA, + GR_ORIGIN_UPPER_LEFT, + fb_emulation_enabled?GR_PIXFMT_RGB_565:GR_PIXFMT_ARGB_8888, //32b color is not compatible with fb emulation + 2, // Double-buffering + 1); // 1 auxillary buffer + } + if (!gfx_context) + gfx_context = grSstWinOpen ((FxU32)NULL, + res_data, + GR_REFRESH_60Hz, + GR_COLORFORMAT_RGBA, + GR_ORIGIN_UPPER_LEFT, + 2, // Double-buffering + 1); // 1 auxillary buffer + + if (!gfx_context) + { + ERRLOG("Error setting display mode"); + // grSstWinClose (gfx_context); + grGlideShutdown (); + return FALSE; + } + + fullscreen = TRUE; + to_fullscreen = FALSE; + + + // get the # of TMUs available + grGet (GR_NUM_TMU, 4, (FxI32*)&voodoo.num_tmu); + // get maximal texture size + grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32*)&voodoo.max_tex_size); + voodoo.sup_large_tex = (voodoo.max_tex_size > 256 && !(settings.hacks & hack_PPL)); + + //num_tmu = 1; + if (voodoo.tex_UMA) + { + GetTexAddr = GetTexAddrUMA; + voodoo.tex_min_addr[0] = voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU0); + voodoo.tex_max_addr[0] = voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU0); + } + else + { + GetTexAddr = GetTexAddrNonUMA; + voodoo.tex_min_addr[0] = grTexMinAddress(GR_TMU0); + voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU1); + voodoo.tex_max_addr[0] = grTexMaxAddress(GR_TMU0); + voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU1); + } + + if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring + voodoo.sup_mirroring = 1; + else + voodoo.sup_mirroring = 0; + + if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension + voodoo.sup_32bit_tex = TRUE; + else + voodoo.sup_32bit_tex = FALSE; + + voodoo.gamma_correction = 0; + if (strstr(extensions, "GETGAMMA")) + grGet(GR_GAMMA_TABLE_ENTRIES, sizeof(voodoo.gamma_table_size), &voodoo.gamma_table_size); + + if (fb_hwfbe_enabled) + { + if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER")) + { + if (!strncmp(extstr, "TEXTUREBUFFER", 13)) + { + char strTextureBufferExt[] = "grTextureBufferExt"; + grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureBufferExt); + char strTextureAuxBufferExt[] = "grTextureAuxBufferExt"; + grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureAuxBufferExt); + char strAuxBufferExt[] = "grAuxBufferExt"; + grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress(strAuxBufferExt); + } + } + else + settings.frame_buffer &= ~fb_hwfbe; + } + else + grTextureBufferExt = 0; + + grStippleModeExt = (GRSTIPPLE)grStippleMode; + grStipplePatternExt = (GRSTIPPLE)grStipplePattern; + + if (grStipplePatternExt) + grStipplePatternExt(settings.stipple_pattern); + +// char strKeyPressedExt[] = "grKeyPressedExt"; +// grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt); + + InitCombine(); + +#ifdef SIMULATE_VOODOO1 + voodoo.num_tmu = 1; + voodoo.sup_mirroring = 0; +#endif + +#ifdef SIMULATE_BANSHEE + voodoo.num_tmu = 1; + voodoo.sup_mirroring = 1; +#endif + + grCoordinateSpace (GR_WINDOW_COORDS); + grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE); + grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE); + grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE); + grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE); + grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE); + grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE); + + grCullMode(GR_CULL_NEGATIVE); + + if (settings.fog) //"FOGCOORD" extension + { + if (strstr (extensions, "FOGCOORD")) + { + GrFog_t fog_t[64]; + guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f); + + for (int i = 63; i > 0; i--) + { + if (fog_t[i] - fog_t[i-1] > 63) + { + fog_t[i-1] = fog_t[i] - 63; + } + } + fog_t[0] = 0; + // for (int f = 0; f < 64; f++) + // { + // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f)); + // } + grFogTable (fog_t); + grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE); + } + else //not supported + settings.fog = FALSE; + } + + grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER); + grDepthBufferFunction(GR_CMP_LESS); + grDepthMask(FXTRUE); + + settings.res_x = settings.scr_res_x; + settings.res_y = settings.scr_res_y; + ChangeSize (); + + guLoadTextures (); + ClearCache (); + + grCullMode (GR_CULL_DISABLE); + grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER); + grDepthBufferFunction (GR_CMP_ALWAYS); + grRenderBuffer(GR_BUFFER_BACKBUFFER); + grColorMask (FXTRUE, FXTRUE); + grDepthMask (FXTRUE); + grBufferClear (0, 0, 0xFFFF); + grBufferSwap (0); + grBufferClear (0, 0, 0xFFFF); + grDepthMask (FXFALSE); + grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR); + grTexFilterMode (1, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR); + grTexClampMode (0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); + grTexClampMode (1, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); + grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); + rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; + +#ifdef TEXTURE_FILTER // Hiroshi Morii + if (!settings.ghq_use) + { + settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs; + if (settings.ghq_use) + { + /* Plugin path */ + int options = texfltr[settings.ghq_fltr]|texenht[settings.ghq_enht]|texcmpr[settings.ghq_cmpr]|texhirs[settings.ghq_hirs]; + if (settings.ghq_enht_cmpr) + options |= COMPRESS_TEX; + if (settings.ghq_hirs_cmpr) + options |= COMPRESS_HIRESTEX; + // if (settings.ghq_enht_tile) + // options |= TILE_TEX; + if (settings.ghq_hirs_tile) + options |= TILE_HIRESTEX; + if (settings.ghq_enht_f16bpp) + options |= FORCE16BPP_TEX; + if (settings.ghq_hirs_f16bpp) + options |= FORCE16BPP_HIRESTEX; + if (settings.ghq_enht_gz) + options |= GZ_TEXCACHE; + if (settings.ghq_hirs_gz) + options |= GZ_HIRESTEXCACHE; + if (settings.ghq_cache_save) + options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE); + if (settings.ghq_hirs_let_texartists_fly) + options |= LET_TEXARTISTS_FLY; + if (settings.ghq_hirs_dump) + options |= DUMP_TEX; + + ghq_dmptex_toggle_key = 0; + + swprintf(romname, sizeof(romname) / sizeof(*romname), L"%hs", rdp.RomName); + swprintf(foldername, sizeof(foldername) / sizeof(*foldername), L"%hs", ConfigGetUserDataPath()); + swprintf(cachename, sizeof(cachename) / sizeof(*cachename), L"%hs", ConfigGetUserCachePath()); + + settings.ghq_use = (int)ext_ghq_init(voodoo.max_tex_size, // max texture width supported by hardware + voodoo.max_tex_size, // max texture height supported by hardware + voodoo.sup_32bit_tex?32:16, // max texture bpp supported by hardware + options, + settings.ghq_cache_size * 1024*1024, // cache texture to system memory + foldername, + cachename, + romname, // name of ROM. must be no longer than 256 characters + DisplayLoadProgress); + } + } + if (settings.ghq_use && strstr (extensions, "TEXMIRROR")) + voodoo.sup_mirroring = 1; +#endif + + return TRUE; +} + +void ReleaseGfx () +{ + VLOG("ReleaseGfx ()\n"); + + // Restore gamma settings + if (voodoo.gamma_correction) + { + if (voodoo.gamma_table_r) + grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); + else + guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop + voodoo.gamma_correction = 0; + } + + // Release graphics + grSstWinClose (gfx_context); + + // Shutdown glide + grGlideShutdown(); + + fullscreen = FALSE; + rdp.window_changed = TRUE; +} + +// new API code begins here! + +#ifdef __cplusplus +extern "C" { +#endif + +EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front) +{ + VLOG("CALL ReadScreen2 ()\n"); + *width = settings.res_x; + *height = settings.res_y; + if (dest) + { + BYTE * line = (BYTE*)dest; + if (!fullscreen) + { + for (wxUint32 y=0; y + if (settings.ghq_use) + { + ext_ghq_shutdown(); + settings.ghq_use = 0; + } +#endif + if (fullscreen) + ReleaseGfx (); + ZLUT_release(); + ClearCache (); + delete[] voodoo.gamma_table_r; + voodoo.gamma_table_r = 0; + delete[] voodoo.gamma_table_g; + voodoo.gamma_table_g = 0; + delete[] voodoo.gamma_table_b; + voodoo.gamma_table_b = 0; +} + +/****************************************************************** +Function: DllTest +Purpose: This function is optional function that is provided +to allow the user to test the dll +input: a handle to the window that calls this function +output: none +*******************************************************************/ +void CALL DllTest ( HWND hParent ) +{ +} + +/****************************************************************** +Function: DrawScreen +Purpose: This function is called when the emulator receives a +WM_PAINT message. This allows the gfx to fit in when +it is being used in the desktop. +input: none +output: none +*******************************************************************/ +void CALL DrawScreen (void) +{ + VLOG ("DrawScreen ()\n"); +} + +/****************************************************************** +Function: GetDllInfo +Purpose: This function allows the emulator to gather information +about the dll by filling in the PluginInfo structure. +input: a pointer to a PLUGIN_INFO stucture that needs to be +filled by the function. (see def above) +output: none +*******************************************************************/ +void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo ) +{ + VLOG ("GetDllInfo ()\n"); + PluginInfo->Version = 0x0103; // Set to 0x0103 + PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX + sprintf (PluginInfo->Name, "Glide64mk2 " G64_VERSION RELTIME); // Name of the DLL + + // If DLL supports memory these memory options then set them to TRUE or FALSE + // if it does not support it + PluginInfo->NormalMemory = TRUE; // a normal wxUint8 array + PluginInfo->MemoryBswaped = TRUE; // a normal wxUint8 array where the memory has been pre + // bswap on a dword (32 bits) boundry +} + +#ifndef WIN32 +BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) +{ + struct timeval tv; + + /* generic routine */ + gettimeofday( &tv, NULL ); + counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000; + return TRUE; +} + +BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) +{ + frequency->s.LowPart= 1000000; + frequency->s.HighPart= 0; + return TRUE; +} +#endif + +/****************************************************************** +Function: InitiateGFX +Purpose: This function is called when the DLL is started to give +information from the emulator that the n64 graphics +uses. This is not called from the emulation thread. +Input: Gfx_Info is passed to this function which is defined +above. +Output: TRUE on success +FALSE on failure to initialise + +** note on interrupts **: +To generate an interrupt set the appropriate bit in MI_INTR_REG +and then call the function CheckInterrupts to tell the emulator +that there is a waiting interrupt. +*******************************************************************/ + +EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info) +{ + VLOG ("InitiateGFX (*)\n"); + voodoo.num_tmu = 2; + + // Assume scale of 1 for debug purposes + rdp.scale_x = 1.0f; + rdp.scale_y = 1.0f; + + memset (&settings, 0, sizeof(SETTINGS)); + ReadSettings (); + char name[21] = "DEFAULT"; + ReadSpecialSettings (name); + settings.res_data_org = settings.res_data; +#ifdef FPS + QueryPerformanceFrequency (&perf_freq); + QueryPerformanceCounter (&fps_last); +#endif + + debug_init (); // Initialize debugger + + gfx = Gfx_Info; + +#ifdef WINPROC_OVERRIDE + // [H.Morii] inject our own winproc so that "alt-enter to fullscreen" + // message is shown when the emulator window is activated. + WNDPROC curWndProc = (WNDPROC)GetWindowLong(gfx.hWnd, GWL_WNDPROC); + if (curWndProc && curWndProc != (WNDPROC)WndProc) { + oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)WndProc); + } +#endif + + util_init (); + math_init (); + TexCacheInit (); + CRC_BuildTable(); + CountCombine(); + if (fb_depth_render_enabled) + ZLUT_init(); + + char strConfigWrapperExt[] = "grConfigWrapperExt"; + GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt); + if (grConfigWrapperExt) + grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic); + + grGlideInit (); + grSstSelect (0); + const char *extensions = grGetString (GR_EXTENSION); + grGlideShutdown (); + if (strstr (extensions, "EVOODOO")) + { + evoodoo = 1; + voodoo.has_2mb_tex_boundary = 0; + } + else { + evoodoo = 0; + voodoo.has_2mb_tex_boundary = 1; + } + + return TRUE; +} + +/****************************************************************** +Function: MoveScreen +Purpose: This function is called in response to the emulator +receiving a WM_MOVE passing the xpos and ypos passed +from that message. +input: xpos - the x-coordinate of the upper-left corner of the +client area of the window. +ypos - y-coordinate of the upper-left corner of the +client area of the window. +output: none +*******************************************************************/ +EXPORT void CALL MoveScreen (int xpos, int ypos) +{ + rdp.window_changed = TRUE; +} + +/****************************************************************** +Function: ResizeVideoOutput +Purpose: This function is called to force us to resize our output OpenGL window. + This is currently unsupported, and should never be called because we do + not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing. +input: new width and height +output: none +*******************************************************************/ +EXPORT void CALL ResizeVideoOutput(int Width, int Height) +{ +} + +/****************************************************************** +Function: RomClosed +Purpose: This function is called when a rom is closed. +input: none +output: none +*******************************************************************/ +EXPORT void CALL RomClosed (void) +{ + VLOG ("RomClosed ()\n"); + + CLOSE_RDP_LOG (); + CLOSE_RDP_E_LOG (); + rdp.window_changed = TRUE; + romopen = FALSE; + if (fullscreen && evoodoo) + ReleaseGfx (); +} + +static void CheckDRAMSize() +{ + wxUint32 test; + GLIDE64_TRY + { + test = gfx.RDRAM[0x007FFFFF] + 1; + } + GLIDE64_CATCH + { + test = 0; + } + if (test) + BMASK = 0x7FFFFF; + else + BMASK = WMASK; +#ifdef LOGGING + sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK); + LOG (out_buf); +#endif +} + +/****************************************************************** +Function: RomOpen +Purpose: This function is called when a rom is open. (from the +emulation thread) +input: none +output: none +*******************************************************************/ +EXPORT int CALL RomOpen (void) +{ + VLOG ("RomOpen ()\n"); + no_dlist = true; + romopen = TRUE; + ucode_error_report = TRUE; // allowed to report ucode errors + rdp_reset (); + + // Get the country code & translate to NTSC(0) or PAL(1) + wxUint16 code = ((wxUint16*)gfx.HEADER)[0x1F^1]; + + if (code == 0x4400) region = 1; // Germany (PAL) + if (code == 0x4500) region = 0; // USA (NTSC) + if (code == 0x4A00) region = 0; // Japan (NTSC) + if (code == 0x5000) region = 1; // Europe (PAL) + if (code == 0x5500) region = 0; // Australia (NTSC) + + char name[21] = "DEFAULT"; + ReadSpecialSettings (name); + + // get the name of the ROM + for (int i=0; i<20; i++) + name[i] = gfx.HEADER[(32+i)^3]; + name[20] = 0; + + // remove all trailing spaces + while (name[strlen(name)-1] == ' ') + name[strlen(name)-1] = 0; + + strncpy(rdp.RomName, name, sizeof(name)); + ReadSpecialSettings (name); + ClearCache (); + + CheckDRAMSize(); + + OPEN_RDP_LOG (); + OPEN_RDP_E_LOG (); + + + // ** EVOODOO EXTENSIONS ** + if (!fullscreen) + { + grGlideInit (); + grSstSelect (0); + } + const char *extensions = grGetString (GR_EXTENSION); + if (!fullscreen) + { + grGlideShutdown (); + + if (strstr (extensions, "EVOODOO")) + evoodoo = 1; + else + evoodoo = 0; + + if (evoodoo) + InitGfx (); + } + + if (strstr (extensions, "ROMNAME")) + { + char strSetRomName[] = "grSetRomName"; + void (FX_CALL *grSetRomName)(char*); + grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName); + grSetRomName (name); + } + // ** + return true; +} + +/****************************************************************** +Function: ShowCFB +Purpose: Useally once Dlists are started being displayed, cfb is +ignored. This function tells the dll to start displaying +them again. +input: none +output: none +*******************************************************************/ +bool no_dlist = true; +EXPORT void CALL ShowCFB (void) +{ + no_dlist = true; + VLOG ("ShowCFB ()\n"); +} + +EXPORT void CALL SetRenderingCallback(void (*callback)(int)) +{ + VLOG("CALL SetRenderingCallback (*)\n"); + renderCallback = callback; +} + +void drawViRegBG() +{ + LRDP("drawViRegBG\n"); + const wxUint32 VIwidth = *gfx.VI_WIDTH_REG; + FB_TO_SCREEN_INFO fb_info; + fb_info.width = VIwidth; + fb_info.height = (wxUint32)rdp.vi_height; + if (fb_info.height == 0) + { + LRDP("Image height = 0 - skipping\n"); + return; + } + fb_info.ul_x = 0; + + fb_info.lr_x = VIwidth - 1; + // fb_info.lr_x = (wxUint32)rdp.vi_width - 1; + fb_info.ul_y = 0; + fb_info.lr_y = fb_info.height - 1; + fb_info.opaque = 1; + fb_info.addr = *gfx.VI_ORIGIN_REG; + fb_info.size = *gfx.VI_STATUS_REG & 3; + rdp.last_bg = fb_info.addr; + + bool drawn = DrawFrameBufferToScreen(fb_info); + if (settings.hacks&hack_Lego && drawn) + { + rdp.updatescreen = 1; + newSwapBuffers (); + DrawFrameBufferToScreen(fb_info); + } +} + +} + +void drawNoFullscreenMessage(); + +void DrawFrameBuffer () +{ + if (!fullscreen) + { + drawNoFullscreenMessage(); + } + if (to_fullscreen) + GoToFullScreen(); + + if (fullscreen) + { + grDepthMask (FXTRUE); + grColorMask (FXTRUE, FXTRUE); + grBufferClear (0, 0, 0xFFFF); + drawViRegBG(); + } +} + +extern "C" { +/****************************************************************** +Function: UpdateScreen +Purpose: This function is called in response to a vsync of the +screen were the VI bit in MI_INTR_REG has already been +set +input: none +output: none +*******************************************************************/ +wxUint32 update_screen_count = 0; +EXPORT void CALL UpdateScreen (void) +{ +#ifdef LOG_KEY + if (CheckKeyPressed(G64_VK_SPACE, 0x0001)) + { + LOG ("KEY!!!\n"); + } +#endif + char out_buf[128]; + sprintf (out_buf, "UpdateScreen (). Origin: %08x, Old origin: %08x, width: %d\n", *gfx.VI_ORIGIN_REG, rdp.vi_org_reg, *gfx.VI_WIDTH_REG); + VLOG (out_buf); + LRDP(out_buf); + + wxUint32 width = (*gfx.VI_WIDTH_REG) << 1; + if (fullscreen && (*gfx.VI_ORIGIN_REG > width)) + update_screen_count++; +//TODO-PORT: wx times +#ifdef FPS + // vertical interrupt has occurred, increment counter + vi_count ++; + + // Check frames per second + LARGE_INTEGER difference; + QueryPerformanceCounter (&fps_next); + difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart; + float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart); + if (diff_secs > 0.5f) + { + fps = (float)(fps_count / diff_secs); + vi = (float)(vi_count / diff_secs); + ntsc_percent = vi / 0.6f; + pal_percent = vi / 0.5f; + fps_last = fps_next; + fps_count = 0; + vi_count = 0; + } +#endif + //* + wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30; + if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0)) + { + LRDP("DirectCPUWrite hack!\n"); + update_screen_count = 0; + no_dlist = true; + ClearCache (); + UpdateScreen(); + return; + } + //*/ + //* + if( no_dlist ) + { + if( *gfx.VI_ORIGIN_REG > width ) + { + ChangeSize (); + LRDP("ChangeSize done\n"); + DrawFrameBuffer(); + LRDP("DrawFrameBuffer done\n"); + rdp.updatescreen = 1; + newSwapBuffers (); + } + return; + } + //*/ + if (settings.swapmode == 0) + newSwapBuffers (); +} + +static void DrawWholeFrameBufferToScreen() +{ + static wxUint32 toScreenCI = 0; + if (rdp.ci_width < 200) + return; + if (rdp.cimg == toScreenCI) + return; + toScreenCI = rdp.cimg; + FB_TO_SCREEN_INFO fb_info; + fb_info.addr = rdp.cimg; + fb_info.size = rdp.ci_size; + fb_info.width = rdp.ci_width; + fb_info.height = rdp.ci_height; + if (fb_info.height == 0) + return; + fb_info.ul_x = 0; + fb_info.lr_x = rdp.ci_width-1; + fb_info.ul_y = 0; + fb_info.lr_y = rdp.ci_height-1; + fb_info.opaque = 0; + DrawFrameBufferToScreen(fb_info); + if (!(settings.frame_buffer & fb_ref)) + memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<>1); +} + +static void GetGammaTable() +{ + char strGetGammaTableExt[] = "grGetGammaTableExt"; + void (FX_CALL *grGetGammaTableExt)(FxU32, FxU32*, FxU32*, FxU32*) = + (void (FX_CALL *)(FxU32, FxU32*, FxU32*, FxU32*))grGetProcAddress(strGetGammaTableExt); + if (grGetGammaTableExt) + { + voodoo.gamma_table_r = new FxU32[voodoo.gamma_table_size]; + voodoo.gamma_table_g = new FxU32[voodoo.gamma_table_size]; + voodoo.gamma_table_b = new FxU32[voodoo.gamma_table_size]; + grGetGammaTableExt(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); + } +} + +} +wxUint32 curframe = 0; +void newSwapBuffers() +{ + if (!rdp.updatescreen) + return; + + rdp.updatescreen = 0; + + LRDP("swapped\n"); + + // Allow access to the whole screen + if (fullscreen) + { + rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; + grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); + grDepthBufferFunction (GR_CMP_ALWAYS); + grDepthMask (FXFALSE); + grCullMode (GR_CULL_DISABLE); + + if ((settings.show_fps & 0xF) || settings.clock) + set_message_combiner (); +#ifdef FPS + float y = (float)settings.res_y; + if (settings.show_fps & 0x0F) + { + if (settings.show_fps & 4) + { + if (region) // PAL + output (0, y, 0, "%d%% ", (int)pal_percent); + else + output (0, y, 0, "%d%% ", (int)ntsc_percent); + y -= 16; + } + if (settings.show_fps & 2) + { + output (0, y, 0, "VI/s: %.02f ", vi); + y -= 16; + } + if (settings.show_fps & 1) + output (0, y, 0, "FPS: %.02f ", fps); + } +#endif + + if (settings.clock) + { + if (settings.clock_24_hr) + { + time_t ltime; + time (<ime); + tm *cur_time = localtime (<ime); + + sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec); + } + else + { + char ampm[] = "AM"; + time_t ltime; + + time (<ime); + tm *cur_time = localtime (<ime); + + if (cur_time->tm_hour >= 12) + { + strcpy (ampm, "PM"); + if (cur_time->tm_hour != 12) + cur_time->tm_hour -= 12; + } + if (cur_time->tm_hour == 0) + cur_time->tm_hour = 12; + + if (cur_time->tm_hour >= 10) + sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm); + else + sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm); + } + output ((float)(settings.res_x - 68), y, 0, out_buf, 0); + } + //hotkeys + if (CheckKeyPressed(G64_VK_BACK, 0x0001)) + { + hotkey_info.hk_filtering = 100; + if (settings.filtering < 2) + settings.filtering++; + else + settings.filtering = 0; + } + if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000)) //alt + + { + if (CheckKeyPressed(G64_VK_B, 0x8000)) //b + { + hotkey_info.hk_motionblur = 100; + hotkey_info.hk_ref = 0; + curframe = frame_count; + settings.frame_buffer ^= fb_motionblur; + } + else if (CheckKeyPressed(G64_VK_V, 0x8000)) //v + { + hotkey_info.hk_ref = 100; + hotkey_info.hk_motionblur = 0; + curframe = frame_count; + settings.frame_buffer ^= fb_ref; + } + } + if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering)) + { + set_message_combiner (); + char buf[256]; + buf[0] = 0; + char * message = 0; + if (hotkey_info.hk_ref) + { + if (settings.frame_buffer & fb_ref) + message = strcat(buf, "FB READ ALWAYS: ON"); + else + message = strcat(buf, "FB READ ALWAYS: OFF"); + hotkey_info.hk_ref--; + } + if (hotkey_info.hk_motionblur) + { + if (settings.frame_buffer & fb_motionblur) + message = strcat(buf, " MOTION BLUR: ON"); + else + message = strcat(buf, " MOTION BLUR: OFF"); + hotkey_info.hk_motionblur--; + } + if (hotkey_info.hk_filtering) + { + switch (settings.filtering) + { + case 0: + message = strcat(buf, " FILTERING MODE: AUTOMATIC"); + break; + case 1: + message = strcat(buf, " FILTERING MODE: FORCE BILINEAR"); + break; + case 2: + message = strcat(buf, " FILTERING MODE: FORCE POINT-SAMPLED"); + break; + } + hotkey_info.hk_filtering--; + } + output (120.0f, (float)settings.res_y, 0, message, 0); + } + } + #ifdef OLDAPI + if (capture_screen) + { + //char path[256]; + // Make the directory if it doesn't exist + if (!wxDirExists(capture_path)) + wxMkdir(capture_path); + wxString path; + wxString romName = rdp.RomName; + romName.Replace(wxT(" "), wxT("_"), true); + romName.Replace(wxT(":"), wxT(";"), true); + + for (int i=1; ; i++) + { + path = capture_path; + path += wxT("Glide64mk2_"); + path += romName; + path += wxT("_"); + if (i < 10) + path += wxT("0"); + path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension; + if (!wxFileName::FileExists(path)) + break; + } + + const wxUint32 offset_x = (wxUint32)rdp.offset_x; + const wxUint32 offset_y = (wxUint32)rdp.offset_y; + const wxUint32 image_width = settings.scr_res_x - offset_x*2; + const wxUint32 image_height = settings.scr_res_y - offset_y*2; + + GrLfbInfo_t info; + info.size = sizeof(GrLfbInfo_t); + if (grLfbLock (GR_LFB_READ_ONLY, + GR_BUFFER_BACKBUFFER, + GR_LFBWRITEMODE_565, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) + { + wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor + int sspos = 0; + wxUint32 offset_src = info.strideInBytes * offset_y; + + // Copy the screen + if (info.writeMode == GR_LFBWRITEMODE_8888) + { + wxUint32 col; + for (wxUint32 y = 0; y < image_height; y++) + { + wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src); + ptr += offset_x; + for (wxUint32 x = 0; x < image_width; x++) + { + col = *(ptr++); + ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF); + ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF); + ssimg[sspos++] = (wxUint8)(col & 0xFF); + } + offset_src += info.strideInBytes; + } + } + else + { + wxUint16 col; + for (wxUint32 y = 0; y < image_height; y++) + { + wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src); + ptr += offset_x; + for (wxUint32 x = 0; x < image_width; x++) + { + col = *(ptr++); + ssimg[sspos++] = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f); + ssimg[sspos++] = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f); + ssimg[sspos++] = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f); + } + offset_src += info.strideInBytes; + } + } + // Unlock the backbuffer + grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER); + wxImage screenshot(image_width, image_height, ssimg); + screenshot.SaveFile(path, ScreenShotFormats[settings.ssformat].type); + capture_screen = 0; + } + } + #endif + + // Capture the screen if debug capture is set + if (_debugger.capture) + { + // Allocate the screen + _debugger.screen = new wxUint8 [(settings.res_x*settings.res_y) << 1]; + + // Lock the backbuffer (already rendered) + GrLfbInfo_t info; + info.size = sizeof(GrLfbInfo_t); + while (!grLfbLock (GR_LFB_READ_ONLY, + GR_BUFFER_BACKBUFFER, + GR_LFBWRITEMODE_565, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)); + + wxUint32 offset_src=0, offset_dst=0; + + // Copy the screen + for (wxUint32 y=0; y> 19) & 0x1F); + g = (wxUint8)((col >> 10) & 0x3F); + b = (wxUint8)((col >> 3) & 0x1F); + dst[x] = (r<<11)|(g<<5)|b; + } + } + else + { + memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1); + } + offset_dst += settings.res_x << 1; + offset_src += info.strideInBytes; + } + + // Unlock the backbuffer + grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER); + } + + if (fullscreen && debugging) + { + debug_keys (); + debug_cacheviewer (); + debug_mouse (); + } + + if (settings.frame_buffer & fb_read_back_to_screen) + DrawWholeFrameBufferToScreen(); + + if (fullscreen) + { + if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo) + grAuxBufferExt( GR_BUFFER_AUXBUFFER ); + grBufferSwap (settings.vsync); + fps_count ++; + if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used + { + if (!voodoo.gamma_correction) + { + if (voodoo.gamma_table_size && !voodoo.gamma_table_r) + GetGammaTable(); //save initial gamma tables + guGammaCorrectionRGB(2.0f, 2.0f, 2.0f); //with gamma=2.0 gamma table is the same, as in N64 + voodoo.gamma_correction = 1; + } + } + else + { + if (voodoo.gamma_correction) + { + if (voodoo.gamma_table_r) + grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b); + else + guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop + voodoo.gamma_correction = 0; + } + } + } + + if (_debugger.capture) + debug_capture (); + + if (fullscreen) + { + if (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6)) + { + if (settings.hacks&hack_RE2 && fb_depth_render_enabled) + grDepthMask (FXFALSE); + else + grDepthMask (FXTRUE); + grBufferClear (0, 0, 0xFFFF); + } + /* //let the game to clear the buffers + else + { + grDepthMask (FXTRUE); + grColorMask (FXFALSE, FXFALSE); + grBufferClear (0, 0, 0xFFFF); + grColorMask (FXTRUE, FXTRUE); + } + */ + } + + if (settings.frame_buffer & fb_read_back_to_screen2) + DrawWholeFrameBufferToScreen(); + + frame_count ++; + + // Open/close debugger? + if (CheckKeyPressed(G64_VK_SCROLL, 0x0001)) + { + if (!debugging) + { + //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768) + { + debugging = 1; + + // Recalculate screen size, don't resize screen + settings.res_x = (wxUint32)(settings.scr_res_x * 0.625f); + settings.res_y = (wxUint32)(settings.scr_res_y * 0.625f); + + ChangeSize (); + } + } + else + { + debugging = 0; + + settings.res_x = settings.scr_res_x; + settings.res_y = settings.scr_res_y; + + ChangeSize (); + } + } + + // Debug capture? + if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001)) + { + _debugger.capture = 1; + } +} + +extern "C" +{ + +/****************************************************************** +Function: ViStatusChanged +Purpose: This function is called to notify the dll that the +ViStatus registers value has been changed. +input: none +output: none +*******************************************************************/ +EXPORT void CALL ViStatusChanged (void) +{ +} + +/****************************************************************** +Function: ViWidthChanged +Purpose: This function is called to notify the dll that the +ViWidth registers value has been changed. +input: none +output: none +*******************************************************************/ +EXPORT void CALL ViWidthChanged (void) +{ +} + +#ifdef WINPROC_OVERRIDE +LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_ACTIVATEAPP: + if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE; + break; + case WM_PAINT: + if (!fullscreen) rdp.window_changed = TRUE; + break; + + /* case WM_DESTROY: + SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc); + break;*/ + } + + return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); +} +#endif + +} + +int CheckKeyPressed(int key, int mask) +{ +static Glide64Keys g64Keys; + if (settings.use_hotkeys == 0) + return 0; +#ifdef __WINDOWS__ + return (GetAsyncKeyState(g64Keys[key]) & mask); +#else + if (grKeyPressed) + return grKeyPressed(g64Keys[key]); +#endif + return 0; +} + + +#ifdef ALTTAB_FIX +int k_ctl=0, k_alt=0, k_del=0; + +LRESULT CALLBACK LowLevelKeyboardProc(int nCode, + WPARAM wParam, LPARAM lParam) +{ + if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam); + + int TabKey = FALSE; + + PKBDLLHOOKSTRUCT p; + + if (nCode == HC_ACTION) + { + switch (wParam) { +case WM_KEYUP: case WM_SYSKEYUP: + p = (PKBDLLHOOKSTRUCT) lParam; + if (p->vkCode == 162) k_ctl = 0; + if (p->vkCode == 164) k_alt = 0; + if (p->vkCode == 46) k_del = 0; + goto do_it; + +case WM_KEYDOWN: case WM_SYSKEYDOWN: + p = (PKBDLLHOOKSTRUCT) lParam; + if (p->vkCode == 162) k_ctl = 1; + if (p->vkCode == 164) k_alt = 1; + if (p->vkCode == 46) k_del = 1; + goto do_it; + +do_it: + TabKey = + ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) || + ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) || + ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) || + (k_ctl && k_alt && k_del); + + break; + } + } + + if (TabKey) + { + k_ctl = 0; + k_alt = 0; + k_del = 0; + ReleaseGfx (); + } + + return CallNextHookEx(NULL, nCode, wParam, lParam); +} +#endif + +// +// DllMain - called when the DLL is loaded, use this to get the DLL's instance +// +#ifdef OLDAPI +class wxDLLApp : public wxApp +{ +public: + virtual bool OnInit(); +}; + +IMPLEMENT_APP_NO_MAIN(wxDLLApp) + +bool wxDLLApp::OnInit() +{ + if (mutexProcessDList == NULL) + mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT); + wxImage::AddHandler(new wxPNGHandler); + wxImage::AddHandler(new wxJPEGHandler); + return true; +} + +#ifndef __WINDOWS__ +int __attribute__ ((constructor)) DllLoad(void); +int __attribute__ ((destructor)) DllUnload(void); +#endif + +// Called when the library is loaded and before dlopen() returns +int DllLoad(void) +{ + int argc = 0; + char **argv = NULL; + wxEntryStart(argc, argv); + if (wxTheApp) + return wxTheApp->CallOnInit() ? TRUE : FALSE; + return 0; +} + +// Called when the library is unloaded and before dlclose() returns +int DllUnload(void) +{ + if ( wxTheApp ) + wxTheApp->OnExit(); + wxEntryCleanup(); + return TRUE; +} + +#ifdef __WINDOWS__ +extern "C" int WINAPI DllMain (HINSTANCE hinstDLL, + wxUint32 fdwReason, + LPVOID lpReserved) +{ + sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason); + LOG (out_buf); + + if (fdwReason == DLL_PROCESS_ATTACH) + { + wxSetInstance(hinstDLL); + return DllLoad(); + } + else if (fdwReason == DLL_PROCESS_DETACH) + { + if (GFXWindow != NULL) + GFXWindow->SetHWND(NULL); + return DllUnload(); + } + return TRUE; +} + +void CALL ReadScreen(void **dest, int *width, int *height) +{ + *width = settings.res_x; + *height = settings.res_y; + wxUint8 * buff = (wxUint8*)malloc(settings.res_x * settings.res_y * 3); + wxUint8 * line = buff; + *dest = (void*)buff; + + if (!fullscreen) + { + for (wxUint32 y=0; y> 16) & 0xFF); + g = (wxUint8)((col >> 8) & 0xFF); + b = (wxUint8)(col & 0xFF); + line[x*3] = b; + line[x*3+1] = g; + line[x*3+2] = r; + } + line += settings.res_x * 3; + offset_src -= info.strideInBytes; + } + } + else + { + wxUint16 col; + for (wxUint32 y=0; y> 11) / 31.0f * 255.0f); + g = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f); + b = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f); + line[x*3] = b; + line[x*3+1] = g; + line[x*3+2] = r; + } + line += settings.res_x * 3; + offset_src -= info.strideInBytes; + } + } + // Unlock the frontbuffer + grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER); + } + LOG ("ReadScreen. Success.\n"); +} +#endif +#endif diff --git a/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/rdp.cpp b/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/rdp.cpp index 5d10a2297c..c8746f289b 100644 --- a/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/rdp.cpp +++ b/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/rdp.cpp @@ -1,151 +1,150 @@ -/* -* Glide64 - Glide video plugin for Nintendo 64 emulators. -* Copyright (c) 2002 Dave2001 -* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski -* -* 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 -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -//**************************************************************** -// -// Glide64 - Glide Plugin for Nintendo 64 emulators -// Project started on December 29th, 2001 -// -// Authors: -// Dave2001, original author, founded the project in 2001, left it in 2002 -// Gugaman, joined the project in 2002, left it in 2002 -// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 -// Hiroshi 'KoolSmoky' Morii, joined the project in 2007 -// -//**************************************************************** -// -// To modify Glide64: -// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. -// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. -// -//**************************************************************** - -#include -#include "Gfx_1.3.h" -#include "m64p.h" -#include "Ini.h" -#include "Config.h" -#include "3dmath.h" -#include "Util.h" -#include "Debugger.h" -#include "Combine.h" -#include "TexCache.h" -#include "TexBuffer.h" -#include "FBtoScreen.h" -#include "CRC.h" - -/* -const int NumOfFormats = 3; -SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} }; -*/ -const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; - -const char *Mode0[] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "NOISE", - "0", "0", - "0", "0", - "0", "0", - "0", "0" }; - -const char *Mode1[] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "CENTER", "K4", - "0", "0", - "0", "0", - "0", "0", - "0", "0" }; - -const char *Mode2[] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "SCALE", "COMBINED_ALPHA", - "T0_ALPHA", "T1_ALPHA", - "PRIM_ALPHA", "SHADE_ALPHA", - "ENV_ALPHA", "LOD_FRACTION", - "PRIM_LODFRAC", "K5", - "0", "0", - "0", "0", - "0", "0", - "0", "0", - "0", "0", - "0", "0", - "0", "0", - "0", "0" }; - -const char *Mode3[] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "0" }; - -const char *Alpha0[] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "0" }; - -#define Alpha1 Alpha0 -const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "PRIM_LODFRAC", "0" }; -#define Alpha3 Alpha0 - -const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" }; -const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" }; -const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"}; -const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" }; - -const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; - -const char *str_yn[] = { "NO", "YES" }; -const char *str_offon[] = { "OFF", "ON" }; - -const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" }; - -// I=intensity probably -const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; -const char *str_size[] = { "4bit", "8bit", "16bit", "32bit" }; -const char *str_cm[] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; -const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" }; -const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; - -const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" }; - -const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; - -const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" }; - -const char *CIStatus[] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", - "ci_old_copy", "ci_copy", "ci_copy_self", - "ci_zcopy", "ci_aux", "ci_aux_copy" }; - +/* +* Glide64 - Glide video plugin for Nintendo 64 emulators. +* Copyright (c) 2002 Dave2001 +* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski +* +* 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 +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//**************************************************************** +// +// Glide64 - Glide Plugin for Nintendo 64 emulators +// Project started on December 29th, 2001 +// +// Authors: +// Dave2001, original author, founded the project in 2001, left it in 2002 +// Gugaman, joined the project in 2002, left it in 2002 +// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 +// Hiroshi 'KoolSmoky' Morii, joined the project in 2007 +// +//**************************************************************** +// +// To modify Glide64: +// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. +// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. +// +//**************************************************************** + +#include +#include "Gfx_1.3.h" +#include "m64p.h" +#include "Config.h" +#include "3dmath.h" +#include "Util.h" +#include "Debugger.h" +#include "Combine.h" +#include "TexCache.h" +#include "TexBuffer.h" +#include "FBtoScreen.h" +#include "CRC.h" + +/* +const int NumOfFormats = 3; +SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} }; +*/ +const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; + +const char *Mode0[] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "NOISE", + "0", "0", + "0", "0", + "0", "0", + "0", "0" }; + +const char *Mode1[] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "CENTER", "K4", + "0", "0", + "0", "0", + "0", "0", + "0", "0" }; + +const char *Mode2[] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "SCALE", "COMBINED_ALPHA", + "T0_ALPHA", "T1_ALPHA", + "PRIM_ALPHA", "SHADE_ALPHA", + "ENV_ALPHA", "LOD_FRACTION", + "PRIM_LODFRAC", "K5", + "0", "0", + "0", "0", + "0", "0", + "0", "0", + "0", "0", + "0", "0", + "0", "0", + "0", "0" }; + +const char *Mode3[] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "0" }; + +const char *Alpha0[] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "0" }; + +#define Alpha1 Alpha0 +const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "PRIM_LODFRAC", "0" }; +#define Alpha3 Alpha0 + +const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" }; +const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" }; +const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"}; +const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" }; + +const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; + +const char *str_yn[] = { "NO", "YES" }; +const char *str_offon[] = { "OFF", "ON" }; + +const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" }; + +// I=intensity probably +const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; +const char *str_size[] = { "4bit", "8bit", "16bit", "32bit" }; +const char *str_cm[] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; +const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" }; +const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; + +const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" }; + +const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; + +const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" }; + +const char *CIStatus[] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", + "ci_old_copy", "ci_copy", "ci_copy_self", + "ci_zcopy", "ci_aux", "ci_aux_copy" }; + typedef struct { int ucode; int crc; -} UcodeData; - +} UcodeData; + static UcodeData UcodeList[] = -{ +{ {0, 0x006bd77f}, {2, 0x03044b84}, {2, 0x030f4b84}, @@ -290,165 +289,165 @@ static UcodeData UcodeList[] = {1, 0xef54ee35}, {21, 0xf9893f70}, {1, 0xfb816260}, - {21, 0xff372492} -}; - -//static variables - -char out_buf[2048]; - -wxUint32 frame_count; // frame counter - -int ucode_error_report = TRUE; -int wrong_tile = -1; - -// ** RDP graphics functions ** -static void undef(); -static void spnoop(); - -static void rdp_noop(); -static void rdp_texrect(); -//static void rdp_texrectflip(); -static void rdp_loadsync(); -static void rdp_pipesync(); -static void rdp_tilesync(); -static void rdp_fullsync(); -static void rdp_setkeygb(); -static void rdp_setkeyr(); -static void rdp_setconvert(); -static void rdp_setscissor(); -static void rdp_setprimdepth(); -static void rdp_setothermode(); -static void rdp_loadtlut(); -static void rdp_settilesize(); -static void rdp_loadblock(); -static void rdp_loadtile(); -static void rdp_settile(); -static void rdp_fillrect(); -static void rdp_setfillcolor(); -static void rdp_setfogcolor(); -static void rdp_setblendcolor(); -static void rdp_setprimcolor(); -static void rdp_setenvcolor(); -static void rdp_setcombine(); -static void rdp_settextureimage(); -static void rdp_setdepthimage(); -static void rdp_setcolorimage(); -static void rdp_trifill(); -static void rdp_trishade(); -static void rdp_tritxtr(); -static void rdp_trishadetxtr(); -static void rdp_trifillz(); -static void rdp_trishadez(); -static void rdp_tritxtrz(); -static void rdp_trishadetxtrz(); -static void rdphalf_1(); -static void rdphalf_2(); -static void rdphalf_cont(); - -static void rsp_reserved0(); -static void rsp_reserved1(); -static void rsp_reserved2(); -static void rsp_reserved3(); - -static void ys_memrect(); - -wxUint8 microcode[4096]; -wxUint32 uc_crc; -void microcheck (); - -// ** UCODE FUNCTIONS ** -#include "ucode00.h" -#include "ucode01.h" -#include "ucode02.h" -#include "ucode03.h" -#include "ucode04.h" -#include "ucode05.h" -#include "ucode06.h" -#include "ucode07.h" -#include "ucode08.h" -#include "ucode09.h" -#include "ucode.h" -#include "ucode09rdp.h" -#include "turbo3D.h" - -static int reset = 0; -static int old_ucode = -1; - -void RDP::Reset() -{ - memset(this, 0, sizeof(RDP_Base)); - // set all vertex numbers - for (int i=0; i>2; i++) - { - uc_crc += ((wxUint32*)microcode)[i]; - } - - FRDP_E ("crc: %08lx\n", uc_crc); - -#ifdef LOG_UCODE - std::ofstream ucf; - ucf.open ("ucode.txt", std::ios::out | std::ios::binary); - char d; - for (i=0; i<0x400000; i++) - { - d = ((char*)gfx.RDRAM)[i^3]; - ucf.write (&d, 1); - } - ucf.close (); -#endif - - FRDP("ucode = %08lx\n", uc_crc); - - int uc = LookupUcode(uc_crc); - - if (uc == -2 && ucode_error_report) - { - settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE); - - ReleaseGfx (); - ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc); - - ucode_error_report = FALSE; // don't report any more ucode errors from this game - } - else if (uc == -1 && ucode_error_report) - { - settings.ucode = 2; //ini->Read(_T("/SETTINGS/ucode"), 0); - - ReleaseGfx (); - ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc); - - ucode_error_report = FALSE; // don't report any more ucode errors from this game - } - else - { - old_ucode = settings.ucode; - settings.ucode = uc; - FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc); - if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented - { - rdp.Persp_en = 1; - rdp.persp_supported = FALSE; - } - else if (settings.texture_correction) - rdp.persp_supported = TRUE; - } -} - -#ifdef __WINDOWS__ -static void GetClientSize(int * width, int * height) -{ -#ifdef __WINDOWS__ - RECT win_rect; - GetClientRect (gfx.hWnd, &win_rect); - *width = win_rect.right; - *height = win_rect.bottom; -#else - GFXWindow->GetClientSize(width, height); -#endif -} -#endif - -void drawNoFullscreenMessage() -{ -//need to find, how to do it on non-windows OS -//the code below will compile on any OS -//but it works only on windows, because -//I don't know, how to initialize GFXWindow on other OS -#ifdef __WINDOWS__ - LOG ("drawNoFullscreenMessage ()\n"); - if (rdp.window_changed) - { - rdp.window_changed = FALSE; - int width, height; - GetClientSize(&width, &height); - - wxClientDC dc(GFXWindow); - dc.SetBrush(*wxMEDIUM_GREY_BRUSH); - dc.SetTextForeground(*wxWHITE); - dc.SetBackgroundMode(wxTRANSPARENT); - dc.DrawRectangle(0, 0, width, height); - - wxCoord w, h; - wxString text = wxT("Glide64mk2"); - dc.GetTextExtent(text, &w, &h); - wxCoord x = (width - w)/2; - wxCoord y = height/2 - h*4; - dc.DrawText(text, x, y); - - text = wxT("Gfx cannot be drawn in windowed mode"); - dc.GetTextExtent(text, &w, &h); - x = (width - w)/2; - y = height/2 - h; - dc.DrawText(text, x, y); - - text = wxT("Press Alt+Enter to switch to fullscreen"); - dc.GetTextExtent(text, &w, &h); - x = (width - w)/2; - y = (height - h)/2 + h*2; - dc.DrawText(text, x, y); - } -#endif -} - -static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y; - -static void DrawPartFrameBufferToScreen() -{ - FB_TO_SCREEN_INFO fb_info; - fb_info.addr = rdp.cimg; - fb_info.size = rdp.ci_size; - fb_info.width = rdp.ci_width; - fb_info.height = rdp.ci_height; - fb_info.ul_x = d_ul_x; - fb_info.lr_x = d_lr_x; - fb_info.ul_y = d_ul_y; - fb_info.lr_y = d_lr_y; - fb_info.opaque = 0; - DrawFrameBufferToScreen(fb_info); - memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<>1); -} - -#define RGBA16TO32(color) \ - ((color&1)?0xFF:0) | \ - ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ - ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ - ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8) - -static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER) -{ - if (!fullscreen) - return; - FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg); - - // don't bother to write the stuff in asm... the slow part is the read from video card, - // not the copy. - - wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG; - wxUint32 height; - if (fb_emulation_enabled && !(settings.hacks&hack_PPL)) - { - int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; - height = rdp.frame_buffers[ind].height; - } - else - { - height = rdp.ci_lower_bound; - if (settings.hacks&hack_PPL) - height -= rdp.ci_upper_bound; - } - FRDP ("width: %d, height: %d... ", width, height); - - if (rdp.scale_x < 1.1f) - { - wxUint16 * ptr_src = new wxUint16[width*height]; - if (grLfbReadRegion(buffer, - (wxUint32)rdp.offset_x, - (wxUint32)rdp.offset_y,//rdp.ci_upper_bound, - width, - height, - width<<1, - ptr_src)) - { - wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); - wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); - wxUint16 c; - - for (wxUint32 y=0; y 0) - c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; - } - else - { - c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; - } - if (rdp.ci_size == 2) - ptr_dst[(x + y * width)^1] = c; - else - ptr_dst32[x + y * width] = RGBA16TO32(c); - } - } - LRDP("ReadRegion. Framebuffer copy complete.\n"); - } - else - { - LRDP("Framebuffer copy failed.\n"); - } - delete[] ptr_src; - } - else - { - if (rdp.motionblur && fb_hwfbe_enabled) - { - return; - } - else - { - float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f) / max(width, rdp.vi_width); - float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height); - - FRDP("width: %d, height: %d, ul_y: %d, lr_y: %d, scale_x: %f, scale_y: %f, ci_width: %d, ci_height: %d\n",width, height, rdp.ci_upper_bound, rdp.ci_lower_bound, scale_x, scale_y, rdp.ci_width, rdp.ci_height); - GrLfbInfo_t info; - info.size = sizeof(GrLfbInfo_t); - - if (grLfbLock (GR_LFB_READ_ONLY, - buffer, - GR_LFBWRITEMODE_565, - GR_ORIGIN_UPPER_LEFT, - FXFALSE, - &info)) - { - wxUint16 *ptr_src = (wxUint16*)info.lfbPtr; - wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); - wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); - wxUint16 c; - wxUint32 stride = info.strideInBytes>>1; - - int read_alpha = settings.frame_buffer & fb_read_alpha; - if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) - read_alpha = FALSE; - int x_start = 0, y_start = 0, x_end = width, y_end = height; - if (settings.hacks&hack_BAR) - { - x_start = 80, y_start = 24, x_end = 240, y_end = 86; - } - for (int y=y_start; y 0) - SwapOK = TRUE; - rdp.updatescreen = 1; - - rdp.tri_n = 0; // 0 triangles so far this frame - rdp.debug_n = 0; - - rdp.model_i = 0; // 0 matrices so far in stack - //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin! - rdp.model_stack_size = min(32, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6); - if (rdp.model_stack_size == 0) - rdp.model_stack_size = 32; - rdp.Persp_en = TRUE; - rdp.fb_drawn = rdp.fb_drawn_front = FALSE; - rdp.update = 0x7FFFFFFF; // All but clear cache - rdp.geom_mode = 0; - rdp.acmp = 0; - rdp.maincimg[1] = rdp.maincimg[0]; - rdp.skip_drawing = FALSE; - rdp.s2dex_tex_loaded = FALSE; - rdp.bg_image_height = 0xFFFF; - fbreads_front = fbreads_back = 0; - rdp.fog_multiplier = rdp.fog_offset = 0; - rdp.zsrc = 0; - if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG) - rdp.tlut_mode = 0; //is it correct? - rdp.scissor_set = FALSE; - ucode5_texshiftaddr = ucode5_texshiftcount = 0; - cpu_fb_write = FALSE; - cpu_fb_read_called = FALSE; - cpu_fb_write_called = FALSE; - cpu_fb_ignore = FALSE; - d_ul_x = 0xffff; - d_ul_y = 0xffff; - d_lr_x = 0; - d_lr_y = 0; - depth_buffer_fog = TRUE; - - //analize possible frame buffer usage - if (fb_emulation_enabled) - DetectFrameBufferUsage(); - if (!(settings.hacks&hack_Lego) || rdp.num_of_ci > 1) - rdp.last_bg = 0; - //* End of set states *// - - // Get the start of the display list and the length of it - wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); - wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4); - FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length, (*gfx.VI_X_SCALE_REG & 0xFFF)/1024.0f, (*gfx.VI_Y_SCALE_REG & 0xFFF)/1024.0f); - FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); - - if (cpu_fb_write == TRUE) - DrawPartFrameBufferToScreen(); - if ((settings.hacks&hack_Tonic) && dlist_length < 16) - { - rdp_fullsync(); - FRDP_E("DLIST is too short!\n"); - return; - } - - // Start executing at the start of the display list - rdp.pc_i = 0; - rdp.pc[rdp.pc_i] = dlist_start; - rdp.dl_count = -1; - rdp.halt = 0; - wxUint32 a; - - // catches exceptions so that it doesn't freeze -#ifdef CATCH_EXCEPTIONS - try { -#endif - if (settings.ucode == ucode_Turbo3d) - { - Turbo3D(); - } - else - { - // MAIN PROCESSING LOOP - do { - - // Get the address of the next command - a = rdp.pc[rdp.pc_i] & BMASK; - - // Load the next command and its input - rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / - // cmd2 and cmd3 are filled only when needed, by the function that needs them - - // Output the address before the command -#ifdef LOG_COMMANDS - FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1); -#else - FRDP ("%08lx: ", a); -#endif - - // Go to the next instruction - rdp.pc[rdp.pc_i] = (a+8) & BMASK; - -#ifdef PERFORMANCE - perf_cur = wxDateTime::UNow(); -#endif - // Process this instruction - gfx_instruction[settings.ucode][rdp.cmd0>>24] (); - - // check DL counter - if (rdp.dl_count != -1) - { - rdp.dl_count --; - if (rdp.dl_count == 0) - { - rdp.dl_count = -1; - - LRDP("End of DL\n"); - rdp.pc_i --; - } - } - -#ifdef PERFORMANCE - perf_next = wxDateTime::UNow(); - sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, (perf_next-perf_cur).Format(_T("%l")).mb_str()); - rdp_log << out_buf; -#endif - - } while (!rdp.halt); - } -#ifdef CATCH_EXCEPTIONS - } catch (...) { - - if (fullscreen) - { - ReleaseGfx (); - rdp_reset (); -#ifdef TEXTURE_FILTER - if (settings.ghq_use) - { - ext_ghq_shutdown(); - settings.ghq_use = 0; - } -#endif - } - ERRLOG("The GFX plugin caused an exception and has been disabled."); - exception = TRUE; - return; - } -#endif - - if (fb_emulation_enabled) - { - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - } - if (settings.frame_buffer & fb_ref) - CopyFrameBuffer (); - if (rdp.cur_image) - CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0)); - - if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) - { - newSwapBuffers (); - CI_SET = FALSE; - } - LRDP("ProcessDList end\n"); -} - -#ifdef __cplusplus -} -#endif - -// undef - undefined instruction, always ignore -static void undef() -{ - FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0); - FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0); -#ifdef _ENDUSER_RELEASE_ - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - rdp.halt = 1; -#endif -} - -// spnoop - no operation, always ignore -static void spnoop() -{ - LRDP("spnoop\n"); -} - -// noop - no operation, always ignore -static void rdp_noop() -{ - LRDP("noop\n"); -} - -static void ys_memrect () -{ - wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); - - wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14); - wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2); - wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); - wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2); - - if (lr_y > rdp.scissor_o.lr_y) - lr_y = rdp.scissor_o.lr_y; - wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5; - wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5; - - FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); - if (off_x > 0) - FRDP (" off_x: %d", off_x); - if (off_y > 0) - FRDP (" off_y: %d", off_y); - LRDP("\n"); - - wxUint32 y, width = lr_x - ul_x; - wxUint32 tex_width = rdp.tiles[tile].line << 3; - wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x; - wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x; - - for (y = ul_y; y < lr_y; y++) { - wxUint8 *src = texaddr + (y - ul_y) * tex_width; - wxUint8 *dst = fbaddr + y * rdp.ci_width; - memcpy (dst, src, width); - } -} - -static void pm_palette_mod () -{ - wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); - wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); - wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); - wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1); - wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); - wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); - wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); - wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); - wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); - for (int i = 0; i < 16; i++) - { - dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; - } - LRDP("Texrect palette modification\n"); -} - -static void pd_zcopy () -{ - wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); - wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1; - wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1; - wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); - wxUint16 width = lr_x - ul_x; - wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u; - wxUint16 c; - for (wxUint16 x=0; x> 8); - ptr_dst[(ul_x+x)^1] = c; - // FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c); - } -} - -static void DrawDepthBufferFog() -{ - if (rdp.zi_width < 200) - return; - FB_TO_SCREEN_INFO fb_info; - fb_info.addr = rdp.zimg; - fb_info.size = 2; - fb_info.width = rdp.zi_width; - fb_info.height = rdp.ci_height; - fb_info.ul_x = rdp.scissor_o.ul_x; - fb_info.lr_x = rdp.scissor_o.lr_x; - fb_info.ul_y = rdp.scissor_o.ul_y; - fb_info.lr_y = rdp.scissor_o.lr_y; - fb_info.opaque = 0; - DrawDepthBufferToScreen(fb_info); -} - -static void rdp_texrect() -{ - if (!rdp.LLE) - { - wxUint32 a = rdp.pc[rdp.pc_i]; - wxUint8 cmdHalf1 = gfx.RDRAM[a+3]; - wxUint8 cmdHalf2 = gfx.RDRAM[a+11]; - a >>= 2; - if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2)) - { - //gSPTextureRectangle - rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1]; - rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3]; - rdp.pc[rdp.pc_i] += 16; - } - else - { - //gDPTextureRectangle - if (settings.hacks&hack_ASB) - rdp.cmd2 = 0; - else - rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0]; - rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1]; - rdp.pc[rdp.pc_i] += 8; - } - } - if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX) - { - ys_memrect(); - return; - } - - if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg))) - { - if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless) - { - pm_palette_mod (); - } - else - { - LRDP("Texrect skipped\n"); - } - return; - } - - if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format) - { - //FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1].addr, rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size); - LRDP("Shadow texrect is skipped.\n"); - rdp.tri_n += 2; - return; - } - - if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy)) - { - pd_zcopy (); - LRDP("Depth buffer copied.\n"); - rdp.tri_n += 2; - return; - } - - if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog - { - if (!depth_buffer_fog) - return; - if (settings.fog) - DrawDepthBufferFog(); - depth_buffer_fog = FALSE; - return; - } - - // FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2); - - float ul_x, ul_y, lr_x, lr_y; - if (rdp.cycle_mode == 2) - { - ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14)); - ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2)); - lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14)); - lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2)); - } - else - { - ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f); - ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f); - lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f); - lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f); - } - - if (ul_x >= lr_x) - { - FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x); - return; - } - - if (rdp.cycle_mode > 1) - { - lr_x += 1.0f; - lr_y += 1.0f; - } else if (lr_y - ul_y < 1.0f) - lr_y = ceil(lr_y); - - if (settings.increase_texrect_edge) - { - if (floor(lr_x) != lr_x) - lr_x = ceil(lr_x); - if (floor(lr_y) != lr_y) - lr_y = ceil(lr_y); - } - - //* - if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect)) - { - LRDP("Attempt to optimize texrect\n"); - if (!rdp.tbuff_tex->drawn) - { - DRAWIMAGE d; - d.imageX = 0; - d.imageW = (wxUint16)rdp.tbuff_tex->width; - d.frameX = (wxUint16)ul_x; - d.frameW = (wxUint16)(rdp.tbuff_tex->width); - - d.imageY = 0; - d.imageH = (wxUint16)rdp.tbuff_tex->height; - d.frameY = (wxUint16)ul_y; - d.frameH = (wxUint16)(rdp.tbuff_tex->height); - FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.tbuff_tex->width, rdp.tbuff_tex->height); - d.scaleX = 1.0f; - d.scaleY = 1.0f; - DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width); - rdp.tbuff_tex->drawn = TRUE; - } - return; - } - //*/ - // framebuffer workaround for Zelda: MM LOT - if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000) - return; - - /*Gonetz*/ - //hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene - if ((settings.hacks&hack_Zelda) && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end) - { - FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.cur_cache[0]->addr, rdp.cimg, rdp.cimg+rdp.ci_width*rdp.ci_height*2); - rdp.tri_n += 2; - return; - } - //* - //hack for Banjo2. it removes black texrects under Banjo - if (!fb_hwfbe_enabled && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000) - { - rdp.tri_n += 2; - return; - } - //*/ - //* - //remove motion blur in night vision - if ((settings.ucode == ucode_PerfectDark) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) - { - if (fb_emulation_enabled) - if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self) - { - //FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1], rdp.maincimg[1]+rdp.ci_width*rdp.ci_height*rdp.ci_size); - LRDP("Wrong Texrect.\n"); - rdp.tri_n += 2; - return; - } - } - //*/ - - int i; - - wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); - - rdp.texrecting = 1; - - wxUint32 prev_tile = rdp.cur_tile; - rdp.cur_tile = tile; - - const float Z = set_sprite_combine_mode (); - - rdp.texrecting = 0; - - if (!rdp.cur_cache[0]) - { - rdp.cur_tile = prev_tile; - rdp.tri_n += 2; - return; - } - // **** - // ** Texrect offset by Gugaman ** - // - //integer representation of texture coordinate. - //needed to detect and avoid overflow after shifting - wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF; - wxInt32 off_y_i = rdp.cmd2 & 0xFFFF; - float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; - float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; - if (off_x_i & 0x8000) //check for sign bit - off_x_i |= ~0xffff; //make it negative - //the same as for off_x_i - if (off_y_i & 0x8000) - off_y_i |= ~0xffff; - - if (rdp.cycle_mode == 2) - dsdx /= 4.0f; - - float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x; - float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x; - float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y; - float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y; - - FRDP("texrect (%.2f, %.2f, %.2f, %.2f), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); - FRDP ("(%f, %f) -> (%f, %f), s: (%d, %d) -> (%d, %d)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y, rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); - FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x_i/32.0f, off_y_i/32.0f, dsdx, dtdy); - - float off_size_x; - float off_size_y; - - if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip - { -#ifdef TEXTURE_FILTER - if (rdp.cur_cache[0]->is_hires_tex) - { - off_size_x = (float)((lr_y - ul_y) * dsdx); - off_size_y = (float)((lr_x - ul_x) * dtdy); - } - else -#endif - { - off_size_x = (lr_y - ul_y - 1) * dsdx; - off_size_y = (lr_x - ul_x - 1) * dtdy; - } - } - else - { -#ifdef TEXTURE_FILTER - if (rdp.cur_cache[0]->is_hires_tex) - { - off_size_x = (float)((lr_x - ul_x) * dsdx); - off_size_y = (float)((lr_y - ul_y) * dtdy); - } - else -#endif - { - off_size_x = (lr_x - ul_x - 1) * dsdx; - off_size_y = (lr_y - ul_y - 1) * dtdy; - } - } - - struct { - float ul_u, ul_v, lr_u, lr_v; - } texUV[2]; //struct for texture coordinates - //angrylion's macro, helps to cut overflowed values. - #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff)) - - //calculate texture coordinates - for (int i = 0; i < 2; i++) - { - if (rdp.cur_cache[i] && (rdp.tex & (i+1))) - { - float sx = 1, sy = 1; - int x_i = off_x_i, y_i = off_y_i; - TILE & tile = rdp.tiles[rdp.cur_tile + i]; - //shifting - if (tile.shift_s) - { - if (tile.shift_s > 10) - { - wxUint8 iShift = (16 - tile.shift_s); - x_i <<= iShift; - sx = (float)(1 << iShift); - } - else - { - wxUint8 iShift = tile.shift_s; - x_i >>= iShift; - sx = 1.0f/(float)(1 << iShift); - } - } - if (tile.shift_t) - { - if (tile.shift_t > 10) - { - wxUint8 iShift = (16 - tile.shift_t); - y_i <<= iShift; - sy = (float)(1 << iShift); - } - else - { - wxUint8 iShift = tile.shift_t; - y_i >>= iShift; - sy = 1.0f/(float)(1 << iShift); - } - } - - if (rdp.aTBuffTex[i]) //hwfbe texture - { - float t0_off_x; - float t0_off_y; - if (off_x_i + off_y_i == 0) - { - t0_off_x = tile.ul_s; - t0_off_y = tile.ul_t; - } - else - { - t0_off_x = off_x_i/32.0f; - t0_off_y = off_y_i/32.0f; - } - t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur - t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t; - texUV[i].ul_u = t0_off_x * sx; - texUV[i].ul_v = t0_off_y * sy; - - texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; - texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; - - texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale; - texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale; - texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale; - texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale; - FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n", - i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v); - } - else //common case - { - //kill 10.5 format overflow by SIGN16 macro - texUV[i].ul_u = SIGN16(x_i) / 32.0f; - texUV[i].ul_v = SIGN16(y_i) / 32.0f; - - texUV[i].ul_u -= tile.f_ul_s; - texUV[i].ul_v -= tile.f_ul_t; - - texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; - texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; - - texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u; - texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u; - texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v; - texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v; - } - } - else - { - texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0; - } - } - rdp.cur_tile = prev_tile; - - // **** - - FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); - - CCLIP2 (s_ul_x, s_lr_x, texUV[0].ul_u, texUV[0].lr_u, texUV[1].ul_u, texUV[1].lr_u, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); - CCLIP2 (s_ul_y, s_lr_y, texUV[0].ul_v, texUV[0].lr_v, texUV[1].ul_v, texUV[1].lr_v, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); - - FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); - - VERTEX vstd[4] = { - { s_ul_x, s_ul_y, Z, 1.0f, texUV[0].ul_u, texUV[0].ul_v, texUV[1].ul_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, - { s_lr_x, s_ul_y, Z, 1.0f, texUV[0].lr_u, texUV[0].ul_v, texUV[1].lr_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, - { s_ul_x, s_lr_y, Z, 1.0f, texUV[0].ul_u, texUV[0].lr_v, texUV[1].ul_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 }, - { s_lr_x, s_lr_y, Z, 1.0f, texUV[0].lr_u, texUV[0].lr_v, texUV[1].lr_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 } }; - - if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip - { - vstd[1].u0 = texUV[0].ul_u; - vstd[1].v0 = texUV[0].lr_v; - vstd[1].u1 = texUV[1].ul_u; - vstd[1].v1 = texUV[1].lr_v; - - vstd[2].u0 = texUV[0].lr_u; - vstd[2].v0 = texUV[0].ul_v; - vstd[2].u1 = texUV[1].lr_u; - vstd[2].v1 = texUV[1].ul_v; - } - - VERTEX *vptr = vstd; - int n_vertices = 4; - - VERTEX *vnew = 0; - // for (int j =0; j < 4; j++) - // FRDP("v[%d] u0: %f, v0: %f, u1: %f, v1: %f\n", j, vstd[j].u0, vstd[j].v0, vstd[j].u1, vstd[j].v1); - - - if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1) - { - // ** LARGE TEXTURE HANDLING ** - // *VERY* simple algebra for texrects - float min_u, min_x, max_u, max_x; - if (vstd[0].u0 < vstd[1].u0) - { - min_u = vstd[0].u0; - min_x = vstd[0].x; - max_u = vstd[1].u0; - max_x = vstd[1].x; - } - else - { - min_u = vstd[1].u0; - min_x = vstd[1].x; - max_u = vstd[0].u0; - max_x = vstd[0].x; - } - - int start_u_256, end_u_256; - start_u_256 = (int)min_u >> 8; - end_u_256 = (int)max_u >> 8; - //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256); - - int splitheight = rdp.cur_cache[0]->splitheight; - - int num_verts_line = 2 + ((end_u_256-start_u_256)<<1); - n_vertices = num_verts_line << 1; - vnew = new VERTEX [n_vertices]; - vptr = vnew; - - vnew[0] = vstd[0]; - vnew[0].u0 -= 256.0f * start_u_256; - vnew[0].v0 += splitheight * start_u_256; - vnew[0].u1 -= 256.0f * start_u_256; - vnew[0].v1 += splitheight * start_u_256; - vnew[1] = vstd[2]; - vnew[1].u0 -= 256.0f * start_u_256; - vnew[1].v0 += splitheight * start_u_256; - vnew[1].u1 -= 256.0f * start_u_256; - vnew[1].v1 += splitheight * start_u_256; - vnew[n_vertices-2] = vstd[1]; - vnew[n_vertices-2].u0 -= 256.0f * end_u_256; - vnew[n_vertices-2].v0 += splitheight * end_u_256; - vnew[n_vertices-2].u1 -= 256.0f * end_u_256; - vnew[n_vertices-2].v1 += splitheight * end_u_256; - vnew[n_vertices-1] = vstd[3]; - vnew[n_vertices-1].u0 -= 256.0f * end_u_256; - vnew[n_vertices-1].v0 += splitheight * end_u_256; - vnew[n_vertices-1].u1 -= 256.0f * end_u_256; - vnew[n_vertices-1].v1 += splitheight * end_u_256; - - // find the equation of the line of u,x - float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u - float b = min_x - m * min_u; // b = y - m * x - - for (i=start_u_256; i 12) - { - float texbound = (float)(splitheight << 1); - for (int k = 0; k < n_vertices; k ++) - { - if (vnew[k].v0 > texbound) - vnew[k].v0 = (float)fmod(vnew[k].v0, texbound); - } - } - //*/ - } - - AllowShadeMods (vptr, n_vertices); - for (i=0; i= RDP::fog_blend) - { - float fog; - if (rdp.fog_mode == RDP::fog_blend) - fog = 1.0f/max(1, rdp.fog_color&0xFF); - else - fog = 1.0f/max(1, (~rdp.fog_color)&0xFF); - for (i = 0; i < n_vertices; i++) - { - vptr[i].f = fog; - } - grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); - } - - ConvertCoordsConvert (vptr, n_vertices); - - if (settings.wireframe) - { - SetWireframeCol (); - grDrawLine (&vstd[0], &vstd[2]); - grDrawLine (&vstd[2], &vstd[1]); - grDrawLine (&vstd[1], &vstd[0]); - grDrawLine (&vstd[2], &vstd[3]); - grDrawLine (&vstd[3], &vstd[1]); - } - else - { - grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX)); - } - - if (_debugger.capture) - { - VERTEX vl[3]; - vl[0] = vstd[0]; - vl[1] = vstd[2]; - vl[2] = vstd[1]; - add_tri (vl, 3, TRI_TEXRECT); - rdp.tri_n ++; - vl[0] = vstd[2]; - vl[1] = vstd[3]; - vl[2] = vstd[1]; - add_tri (vl, 3, TRI_TEXRECT); - rdp.tri_n ++; - } - else - rdp.tri_n += 2; - } - else - { - rdp.tri_n += 2; - } - - delete[] vnew; -} - -static void rdp_loadsync() -{ - LRDP("loadsync - ignored\n"); -} - -static void rdp_pipesync() -{ - LRDP("pipesync - ignored\n"); -} - -static void rdp_tilesync() -{ - LRDP("tilesync - ignored\n"); -} - -static void rdp_fullsync() -{ - // Set an interrupt to allow the game to continue - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - LRDP("fullsync\n"); -} - -static void rdp_setkeygb() -{ - wxUint32 sB = rdp.cmd1&0xFF; - wxUint32 cB = (rdp.cmd1>>8)&0xFF; - wxUint32 sG = (rdp.cmd1>>16)&0xFF; - wxUint32 cG = (rdp.cmd1>>24)&0xFF; - rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8); - rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8); - FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB); -} - -static void rdp_setkeyr() -{ - wxUint32 sR = rdp.cmd1&0xFF; - wxUint32 cR = (rdp.cmd1>>8)&0xFF; - rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24); - rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24); - FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR); -} - -static void rdp_setconvert() -{ - /* - rdp.YUV_C0 = 1.1647f ; - rdp.YUV_C1 = 0.79931f ; - rdp.YUV_C2 = -0.1964f ; - rdp.YUV_C3 = -0.40651f; - rdp.YUV_C4 = 1.014f ; - */ - rdp.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF; - rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF); - // RDP_E("setconvert - IGNORED\n"); - FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5); -} - -// -// setscissor - sets the screen clipping rectangle -// - -static void rdp_setscissor() -{ - // clipper resolution is 320x240, scale based on computer resolution - rdp.scissor_o.ul_x = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; - rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; - rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; - rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; - - rdp.ci_upper_bound = rdp.scissor_o.ul_y; - rdp.ci_lower_bound = rdp.scissor_o.lr_y; - rdp.scissor_set = TRUE; - - FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y, - rdp.scissor_o.lr_x, rdp.scissor_o.lr_y); - - rdp.update |= UPDATE_SCISSOR; - - if (rdp.view_scale[0] == 0) //viewport is not set? - { - rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x; - rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y; - rdp.view_trans[0] = rdp.view_scale[0]; - rdp.view_trans[1] = -rdp.view_scale[1]; - rdp.update |= UPDATE_VIEWPORT; - } -} - -static void rdp_setprimdepth() -{ - rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF); - rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF); - - FRDP("setprimdepth: %d\n", rdp.prim_depth); -} - -static void rdp_setothermode() -{ -#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \ - rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \ - rdp.cmd1 = data; \ - gfx_instruction[settings.ucode][cmd] (); \ -} -#define SETOTHERMODE(cmd,sft,len,data) { \ - rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \ - rdp.cmd1 = data; \ - gfx_instruction[settings.ucode][cmd] (); \ -} - - LRDP("rdp_setothermode\n"); - - if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD)) - { - int cmd0 = rdp.cmd0; - F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L - F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H - } - else - { - int cmd0 = rdp.cmd0; - SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L - SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H - } -} - -void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count) -{ - LRDP("Loading palette... "); - wxUint16 *dpal = rdp.pal_8 + start; - wxUint16 end = start+count; -#ifdef TEXTURE_FILTER - wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK)); -#endif - - for (wxUint16 i=start; i>= 4; - end = start + (count >> 4); - if (end == start) // it can be if count < 16 - end = start + 1; - for (wxUint16 p = start; p < end; p++) - { - rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); - } - rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); - LRDP("Done.\n"); -} - -static void rdp_loadtlut() -{ - wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; - wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes - // wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1; - wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy - - if (rdp.timg.addr + (count<<1) > BMASK) - count = (wxUint16)((BMASK - rdp.timg.addr) >> 1); - - if (start+count > 256) count = 256-start; - - FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count, - rdp.timg.addr); - - load_palette (rdp.timg.addr, start, count); - - rdp.timg.addr += count << 1; - - if (rdp.tbuff_tex) //paranoid check. - { - //the buffer is definitely wrong, as there must be no CI frame buffers - //find and remove it - for (int i = 0; i < voodoo.num_tmu; i++) - { - for (int j = 0; j < rdp.texbufs[i].count; j++) - { - if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex) - { - rdp.texbufs[i].count--; - if (j < rdp.texbufs[i].count) - memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j)); - return; - } - } - } - } -} - -int tile_set = 0; -static void rdp_settilesize() -{ - wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; - rdp.last_tile_size = tile; - - rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f; - rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f; - - int ul_s = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff); - int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff); - int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff); - int lr_t = (((wxUint16)(rdp.cmd1 >> 2 )) & 0x03ff); - - if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size - wrong_tile = tile; - else if (wrong_tile == (int)tile) - wrong_tile = -1; - - if (settings.use_sts1_only) - { - // ** USE FIRST SETTILESIZE ONLY ** - // This option helps certain textures while using the 'Alternate texture size method', - // but may break others. (should help more than break) - - if (tile_set) - { - // coords in 10.2 format - rdp.tiles[tile].ul_s = ul_s; - rdp.tiles[tile].ul_t = ul_t; - rdp.tiles[tile].lr_s = lr_s; - rdp.tiles[tile].lr_t = lr_t; - tile_set = 0; - } - } - else - { - // coords in 10.2 format - rdp.tiles[tile].ul_s = ul_s; - rdp.tiles[tile].ul_t = ul_t; - rdp.tiles[tile].lr_s = lr_s; - rdp.tiles[tile].lr_t = lr_t; - } - - // handle wrapping - if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400; - if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400; - - rdp.update |= UPDATE_TEXTURE; - - rdp.first = 1; - - FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n", - tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t); -} - -void setTBufTex(wxUint16 t_mem, wxUint32 cnt) -{ - FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt); - TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex; - for (int i = 0; i < 2; i++) - { - LRDP("Before: "); - if (rdp.aTBuffTex[i]) { - FRDP("rdp.aTBuffTex[%d]: tmu=%d t_mem=%d tile=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem, rdp.aTBuffTex[i]->tile); - } else { - FRDP("rdp.aTBuffTex[%d]=0\n", i); - } - if ((rdp.aTBuffTex[i] == 0 && rdp.aTBuffTex[i^1] != pTbufTex) || (rdp.aTBuffTex[i] && rdp.aTBuffTex[i]->t_mem >= t_mem && rdp.aTBuffTex[i]->t_mem < t_mem + cnt)) - { - if (pTbufTex) - { - rdp.aTBuffTex[i] = pTbufTex; - rdp.aTBuffTex[i]->t_mem = t_mem; - pTbufTex = 0; - FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem); - } - else - { - rdp.aTBuffTex[i] = 0; - FRDP("rdp.aTBuffTex[%d]=0\n", i); - } - } - } -} - -static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt) -{ - uint32_t *v5; - int v6; - uint32_t *v7; - uint32_t v8; - int v9; - uint32_t v10; - uint32_t *v11; - uint32_t v12; - uint32_t v13; - uint32_t v14; - int v15; - int v16; - uint32_t *v17; - int v18; - uint32_t v19; - uint32_t v20; - int i; - - v5 = dst; - v6 = cnt; - if ( cnt ) - { - v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC)); - v8 = off & 3; - if ( !(off & 3) ) - goto LABEL_23; - v9 = 4 - v8; - v10 = *v7; - v11 = v7 + 1; - do - { - v10 = __ROL__(v10, 8); - --v8; - } - while ( v8 ); - do - { - v10 = __ROL__(v10, 8); - *(uint8_t *)v5 = v10; - v5 = (uint32_t *)((char *)v5 + 1); - --v9; - } - while ( v9 ); - v12 = *v11; - v7 = v11 + 1; - *v5 = bswap32(v12); - ++v5; - v6 = cnt - 1; - if ( cnt != 1 ) - { -LABEL_23: - do - { - *v5 = bswap32(*v7); - v5[1] = bswap32(v7[1]); - v7 += 2; - v5 += 2; - --v6; - } - while ( v6 ); - } - v13 = off & 3; - if ( off & 3 ) - { - v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC)); - do - { - v14 = __ROL__(v14, 8); - *(uint8_t *)v5 = v14; - v5 = (uint32_t *)((char *)v5 + 1); - --v13; - } - while ( v13 ); - } - } - v15 = cnt; - v16 = 0; - v17 = dst; - v18 = 0; -dxt_test: - while ( 1 ) - { - v17 += 2; - --v15; - if ( !v15 ) - break; - v16 += dxt; - if ( v16 < 0 ) - { - while ( 1 ) - { - ++v18; - --v15; - if ( !v15 ) - goto end_dxt_test; - v16 += dxt; - if ( v16 >= 0 ) - { - for ( i = v15; v18; --v18 ) - { - v19 = *v17; - *v17 = v17[1]; - v17[1] = v19; - v17 += 2; - } - v15 = i; - goto dxt_test; - } - } - } - } -end_dxt_test: - while ( v18 ) - { - v20 = *v17; - *v17 = v17[1]; - v17[1] = v20; - v17 += 2; - --v18; - } -} - -void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt); -static void rdp_loadblock() -{ - if (rdp.skip_drawing) - { - LRDP("loadblock skipped\n"); - return; - } - wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); - wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF); - wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF; - if (ucode5_texshiftaddr) - { - if (ucode5_texshift % ((lr_s+1)<<3)) - { - rdp.timg.addr -= ucode5_texshift; - ucode5_texshiftaddr = 0; - ucode5_texshift = 0; - ucode5_texshiftcount = 0; - } - else - ucode5_texshiftcount++; - } - - rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; - - // ** DXT is used for swapping every other line - /* double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error - wxUint32 _dxt = (wxUint32)fdxt;*/ - - // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) - wxUint32 _dxt = dxt << 20; - - wxUint32 addr = segoffset(rdp.timg.addr) & BMASK; - - // lr_s specifies number of 64-bit words to copy - // 10.2 format - wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF; - wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF; - - rdp.tiles[tile].ul_s = ul_s; - rdp.tiles[tile].ul_t = ul_t; - rdp.tiles[tile].lr_s = lr_s; - - rdp.timg.set_by = 0; // load block - -#ifdef TEXTURE_FILTER - LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; - info.tile_width = lr_s; - info.dxt = dxt; -#endif - - // do a quick boundary check before copying to eliminate the possibility for exception - if (ul_s >= 512) { - lr_s = 1; // 1 so that it doesn't die on memcpy - ul_s = 511; - } - if (ul_s+lr_s > 512) - lr_s = 512-ul_s; - - if (addr+(lr_s<<3) > BMASK+1) - lr_s = (wxUint16)((BMASK-addr)>>3); - - //angrylion's advice to use ul_s in texture image offset and cnt calculations. - //Helps to fix Vigilante 8 jpeg backgrounds and logos - wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1); - unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); - wxUint32 cnt = lr_s-ul_s+1; - if (rdp.tiles[tile].size == 3) - cnt <<= 1; - - if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) { - WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem)); - cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem); - } - - if (rdp.timg.size == 3) - LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt); - else - loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt); - - rdp.timg.addr += cnt << 3; - rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11); - - rdp.update |= UPDATE_TEXTURE; - - FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n", - tile, ul_s, ul_t, lr_s, - dxt, _dxt); - - if (fb_hwfbe_enabled) - setTBufTex(rdp.tiles[tile].t_mem, cnt); -} - - -static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end) -{ - uint32_t *v7; - int v8; - uint32_t *v9; - int v10; - int v11; - int v12; - uint32_t *v13; - int v14; - int v15; - uint32_t v16; - uint32_t *v17; - uint32_t v18; - int v19; - uint32_t v20; - int v21; - uint32_t v22; - int v23; - uint32_t *v24; - int v25; - int v26; - uint32_t *v27; - int v28; - int v29; - int v30; - uint32_t *v31; - - v7 = dst; - v8 = width; - v9 = src; - v10 = off; - v11 = 0; - v12 = height; - do - { - if ( end < v7 ) - break; - v31 = v7; - v30 = v8; - v29 = v12; - v28 = v11; - v27 = v9; - v26 = v10; - if ( v8 ) - { - v25 = v8; - v24 = v9; - v23 = v10; - v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC)); - v14 = v10 & 3; - if ( !(v10 & 3) ) - goto LABEL_20; - v15 = 4 - v14; - v16 = *v13; - v17 = v13 + 1; - do - { - v16 = __ROL__(v16, 8); - --v14; - } - while ( v14 ); - do - { - v16 = __ROL__(v16, 8); - *(uint8_t *)v7 = v16; - v7 = (uint32_t *)((char *)v7 + 1); - --v15; - } - while ( v15 ); - v18 = *v17; - v13 = v17 + 1; - *v7 = bswap32(v18); - ++v7; - --v8; - if ( v8 ) - { -LABEL_20: - do - { - *v7 = bswap32(*v13); - v7[1] = bswap32(v13[1]); - v13 += 2; - v7 += 2; - --v8; - } - while ( v8 ); - } - v19 = v23 & 3; - if ( v23 & 3 ) - { - v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC)); - do - { - v20 = __ROL__(v20, 8); - *(uint8_t *)v7 = v20; - v7 = (uint32_t *)((char *)v7 + 1); - --v19; - } - while ( v19 ); - } - } - v9 = v27; - v21 = v29; - v8 = v30; - v11 = v28 ^ 1; - if ( v28 == 1 ) - { - v7 = v31; - if ( v30 ) - { - do - { - v22 = *v7; - *v7 = v7[1]; - v7[1] = v22; - v7 += 2; - --v8; - } - while ( v8 ); - } - v21 = v29; - v8 = v30; - } - v10 = line + v26; - v12 = v21 - 1; - } - while ( v12 ); -} - -void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height); -static void rdp_loadtile() -{ - if (rdp.skip_drawing) - { - LRDP("loadtile skipped\n"); - return; - } - rdp.timg.set_by = 1; // load tile - - wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); - - rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; - - wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF); - wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF); - wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF); - wxUint16 lr_t = (wxUint16)((rdp.cmd1 >> 2 ) & 0x03FF); - - if (lr_s < ul_s || lr_t < ul_t) return; - - if (wrong_tile >= 0) //there was a tile with zero length - { - rdp.tiles[wrong_tile].lr_s = lr_s; - - if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size) - rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size); - else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size) - rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size); - rdp.tiles[wrong_tile].lr_t = lr_t; - rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0; - // wrong_tile = -1; - } - - if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0)) - { - FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); - rdp.tbuff_tex->tile_uls = ul_s; - rdp.tbuff_tex->tile_ult = ul_t; - } - - if ((settings.hacks&hack_Tonic) && tile == 7) - { - rdp.tiles[0].ul_s = ul_s; - rdp.tiles[0].ul_t = ul_t; - rdp.tiles[0].lr_s = lr_s; - rdp.tiles[0].lr_t = lr_t; - } - - wxUint32 height = lr_t - ul_t + 1; // get height - wxUint32 width = lr_s - ul_s + 1; - -#ifdef TEXTURE_FILTER - LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; - info.tile_ul_s = ul_s; - info.tile_ul_t = ul_t; - info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<> 1; - wxUint32 offs = ul_t * line_n; - offs += ul_s << rdp.tiles[tile].size >> 1; - offs += rdp.timg.addr; - if (offs >= BMASK) - return; - - if (rdp.timg.size == 3) - { - LoadTile32b(tile, ul_s, ul_t, width, height); - } - else - { - // check if points to bad location - if (offs + line_n*height > BMASK) - height = (BMASK - offs) / line_n; - if (height == 0) - return; - - wxUint32 wid_64 = rdp.tiles[tile].line; - unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); - unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3); - loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end); - } - FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile, - ul_s, ul_t, lr_s, lr_t); - - if (fb_hwfbe_enabled) - setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height); -} - -static void rdp_settile() -{ - tile_set = 1; // used to check if we only load the first settilesize - - rdp.first = 0; - - rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); - TILE *tile = &rdp.tiles[rdp.last_tile]; - - tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); - tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); - tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF); - tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF); - tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F); - tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01); - tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01); - tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F); - tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F); - tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01); - tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01); - tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F); - tile->shift_s = (wxUint8)(rdp.cmd1 & 0x0F); - - rdp.update |= UPDATE_TEXTURE; - - FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, " - "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, " - "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n", - rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line, - tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t, - tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s); - - if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2) - { - for (int i = 0; i < 2; i++) - { - if (rdp.aTBuffTex[i]) - { - if (rdp.aTBuffTex[i]->t_mem == tile->t_mem) - { - if (rdp.aTBuffTex[i]->size == tile->size) - { - rdp.aTBuffTex[i]->tile = rdp.last_tile; - rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88; - FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88"); - } - else - rdp.aTBuffTex[i] = 0; - break; - } - else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same - rdp.aTBuffTex[i] = 0; - } - } - } -} - -// -// fillrect - fills a rectangle -// - -static void rdp_fillrect() -{ - wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); - wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; - wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; - wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; - if ((ul_x > lr_x) || (ul_y > lr_y)) - { - LRDP("Fillrect. Wrong coordinates. Skipped\n"); - return; - } - int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC); - if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer) - { - LRDP("Fillrect - cleared the depth buffer\n"); - if (fullscreen) - { - if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers - { - update_scissor (); - grDepthMask (FXTRUE); - grColorMask (FXFALSE, FXFALSE); - grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF); - grColorMask (FXTRUE, FXTRUE); - rdp.update |= UPDATE_ZBUF_ENABLED; - } - //if (settings.frame_buffer&fb_depth_clear) - { - ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); - lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); - ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); - lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); - wxUint32 zi_width_in_dwords = rdp.ci_width >> 1; - ul_x >>= 1; - lr_x >>= 1; - wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg); - dst += ul_y * zi_width_in_dwords; - for (wxUint32 y = ul_y; y < lr_y; y++) - { - for (wxUint32 x = ul_x; x < lr_x; x++) - { - dst[x] = rdp.fill_color; - } - dst += zi_width_in_dwords; - } - } - } - return; - } - - if (rdp.skip_drawing) - { - LRDP("Fillrect skipped\n"); - return; - } - - if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x - ul_x) && (rdp.cur_image->height == lr_y - ul_y)) - { - wxUint32 color = rdp.fill_color; - if (rdp.ci_size < 3) - { - color = ((color&1)?0xFF:0) | - ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | - ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | - ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); - } - grDepthMask (FXFALSE); - grBufferClear (color, 0, 0xFFFF); - grDepthMask (FXTRUE); - rdp.update |= UPDATE_ZBUF_ENABLED; - LRDP("Fillrect - cleared the texture buffer\n"); - return; - } - - // Update scissor - if (fullscreen) - update_scissor (); - - if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0) - { - lr_x--; lr_y--; - } - FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode, - rdp.tri_n, rdp.tri_n+1); - - FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, - rdp.scissor.lr_y); - - // KILL the floating point error with 0.01f - wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); - wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); - wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); - wxInt32 s_lr_y = (wxUint32)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); - - if (s_lr_x < 0) s_lr_x = 0; - if (s_lr_y < 0) s_lr_y = 0; - if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x; - if ((wxUint32)s_ul_y > settings.res_y) s_ul_y = settings.res_y; - - FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); - - if (fullscreen) - { - grFogMode (GR_FOG_DISABLE); - - const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode(); - - // Draw the rectangle - VERTEX v[4] = { - { (float)s_ul_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, - { (float)s_lr_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, - { (float)s_ul_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, - { (float)s_lr_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0} }; - - if (rdp.cycle_mode == 3) - { - wxUint32 color = rdp.fill_color; - - if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) - { - //background of auxiliary frame buffers must have zero alpha. - //make it black, set 0 alpha to plack pixels on frame buffer read - color = 0; - } - else if (rdp.ci_size < 3) - { - color = ((color&1)?0xFF:0) | - ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | - ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | - ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); - } - - grConstantColorValue (color); - - grColorCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_CONSTANT, - GR_COMBINE_OTHER_NONE, - FXFALSE); - - grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_CONSTANT, - GR_COMBINE_OTHER_NONE, - FXFALSE); - - grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); - - grAlphaTestFunction (GR_CMP_ALWAYS); - if (grStippleModeExt) - grStippleModeExt(GR_STIPPLE_DISABLE); - - grCullMode(GR_CULL_DISABLE); - grFogMode (GR_FOG_DISABLE); - grDepthBufferFunction (GR_CMP_ALWAYS); - grDepthMask (FXFALSE); - - rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED; - } - else - { - wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); - wxUint32 cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); - if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade - { - AllowShadeMods (v, 4); - for (int k = 0; k < 4; k++) - apply_shade_mods (&v[k]); - } - if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64 - { - grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_CONSTANT, - GR_COMBINE_OTHER_NONE, - FXFALSE); - grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF)); - rdp.update |= UPDATE_COMBINE; - } - } - - if (settings.wireframe) - { - SetWireframeCol (); - grDrawLine (&v[0], &v[2]); - grDrawLine (&v[2], &v[1]); - grDrawLine (&v[1], &v[0]); - grDrawLine (&v[2], &v[3]); - grDrawLine (&v[3], &v[1]); - //grDrawLine (&v[1], &v[2]); - } - else - { - grDrawTriangle (&v[0], &v[2], &v[1]); - grDrawTriangle (&v[2], &v[3], &v[1]); - } - - if (_debugger.capture) - { - VERTEX v1[3]; - v1[0] = v[0]; - v1[1] = v[2]; - v1[2] = v[1]; - add_tri (v1, 3, TRI_FILLRECT); - rdp.tri_n ++; - v1[0] = v[2]; - v1[1] = v[3]; - add_tri (v1, 3, TRI_FILLRECT); - rdp.tri_n ++; - } - else - rdp.tri_n += 2; - } - else - { - rdp.tri_n += 2; - } -} - -// -// setfillcolor - sets the filling color -// - -static void rdp_setfillcolor() -{ - rdp.fill_color = rdp.cmd1; - rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; - - FRDP("setfillcolor: %08lx\n", rdp.cmd1); -} - -static void rdp_setfogcolor() -{ - rdp.fog_color = rdp.cmd1; - rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED; - - FRDP("setfogcolor - %08lx\n", rdp.cmd1); -} - -static void rdp_setblendcolor() -{ - rdp.blend_color = rdp.cmd1; - rdp.update |= UPDATE_COMBINE; - - FRDP("setblendcolor: %08lx\n", rdp.cmd1); -} - -static void rdp_setprimcolor() -{ - rdp.prim_color = rdp.cmd1; - rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF; - rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin); - rdp.update |= UPDATE_COMBINE; - - FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin, - rdp.prim_lodfrac); -} - -static void rdp_setenvcolor() -{ - rdp.env_color = rdp.cmd1; - rdp.update |= UPDATE_COMBINE; - - FRDP("setenvcolor: %08lx\n", rdp.cmd1); -} - -static void rdp_setcombine() -{ - rdp.c_a0 = (wxUint8)((rdp.cmd0 >> 20) & 0xF); - rdp.c_b0 = (wxUint8)((rdp.cmd1 >> 28) & 0xF); - rdp.c_c0 = (wxUint8)((rdp.cmd0 >> 15) & 0x1F); - rdp.c_d0 = (wxUint8)((rdp.cmd1 >> 15) & 0x7); - rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7); - rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7); - rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9) & 0x7); - rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9) & 0x7); - - rdp.c_a1 = (wxUint8)((rdp.cmd0 >> 5) & 0xF); - rdp.c_b1 = (wxUint8)((rdp.cmd1 >> 24) & 0xF); - rdp.c_c1 = (wxUint8)((rdp.cmd0 >> 0) & 0x1F); - rdp.c_d1 = (wxUint8)((rdp.cmd1 >> 6) & 0x7); - rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7); - rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3) & 0x7); - rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7); - rdp.c_Ad1 = (wxUint8)((rdp.cmd1 >> 0) & 0x7); - - rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)| - (rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25); - rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)| - (rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25); - - rdp.update |= UPDATE_COMBINE; - - FRDP("setcombine\na0=%s b0=%s c0=%s d0=%s\nAa0=%s Ab0=%s Ac0=%s Ad0=%s\na1=%s b1=%s c1=%s d1=%s\nAa1=%s Ab1=%s Ac1=%s Ad1=%s\n", - Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0], - Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0], - Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1], - Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]); -} - -// -// settextureimage - sets the source for an image copy -// - -static void rdp_settextureimage() -{ - static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; - static const char *size[] = { "4bit", "8bit", "16bit", "32bit" }; - - rdp.timg.format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); - rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); - rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF)); - rdp.timg.addr = segoffset(rdp.cmd1); - if (ucode5_texshiftaddr) - { - if (rdp.timg.format == 0) - { - wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr); - ucode5_texshift = t[ucode5_texshiftcount^1]; - rdp.timg.addr += ucode5_texshift; - } - else - { - ucode5_texshiftaddr = 0; - ucode5_texshift = 0; - ucode5_texshiftcount = 0; - } - } - rdp.s2dex_tex_loaded = TRUE; - rdp.update |= UPDATE_TEXTURE; - - if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end)) - { - if (!rdp.fb_drawn) - { - if (!rdp.cur_image) - CopyFrameBuffer(); - else - CloseTextureBuffer(TRUE); - rdp.fb_drawn = TRUE; - } - } - - if (fb_hwfbe_enabled) //search this texture among drawn texture buffers - FindTextureBuffer(rdp.timg.addr, rdp.timg.width); - - FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n", - format[rdp.timg.format], size[rdp.timg.size], - rdp.timg.width, rdp.timg.addr); -} - -static void rdp_setdepthimage() -{ - rdp.zimg = segoffset(rdp.cmd1) & BMASK; - rdp.zi_width = rdp.ci_width; - FRDP("setdepthimage - %08lx\n", rdp.zimg); -} - -int SwapOK = TRUE; -static void RestoreScale() -{ - FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak); - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - // update_scissor(); - rdp.view_scale[0] *= rdp.scale_x; - rdp.view_scale[1] *= rdp.scale_y; - rdp.view_trans[0] *= rdp.scale_x; - rdp.view_trans[1] *= rdp.scale_y; - rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; - //* - if (fullscreen) - { - grDepthMask (FXFALSE); - grBufferClear (0, 0, 0xFFFF); - grDepthMask (FXTRUE); - } - //*/ -} - -static wxUint32 swapped_addr = 0; - -static void rdp_setcolorimage() -{ - if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF)) - { - COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count]; - COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count?rdp.ci_count-1:0]; - COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; - switch (cur_fb.status) - { - case ci_main: - { - - if (rdp.ci_count == 0) - { - if ((rdp.ci_status == ci_aux)) //for PPL - { - float sx = rdp.scale_x; - float sy = rdp.scale_y; - rdp.scale_x = 1.0f; - rdp.scale_y = 1.0f; - CopyFrameBuffer (); - rdp.scale_x = sx; - rdp.scale_y = sy; - } - if (!fb_hwfbe_enabled) - { - if ((rdp.num_of_ci > 1) && - (next_fb.status == ci_aux) && - (next_fb.width >= cur_fb.width)) - { - rdp.scale_x = 1.0f; - rdp.scale_y = 1.0f; - } - } - else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index)) - { - if (next_fb.status == ci_aux_copy) - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - else - OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]); - } - else if (fb_hwfbe_enabled && prev_fb.status == ci_aux) - { - if (rdp.motionblur) - { - rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]); - grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); - grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2, - rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH ); - } - else if (rdp.read_whole_frame) - { - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - } - //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index) - // CloseTextureBuffer(); - - rdp.skip_drawing = FALSE; - } - break; - case ci_copy: - { - if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) - { - if (cur_fb.width == rdp.ci_width) - { - if (CopyTextureBuffer(prev_fb, cur_fb)) - { - // if (CloseTextureBuffer(TRUE)) - //* - if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM - { - CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); - rdp.fb_drawn = TRUE; - memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<>1); - } - //*/ - } - else - { - if (!rdp.fb_drawn || prev_fb.status == ci_copy_self) - { - CopyFrameBuffer (); - rdp.fb_drawn = TRUE; - } - memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<>1); - } - } - else - { - CloseTextureBuffer(TRUE); - } - } - else - { - memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size); - } - rdp.skip_drawing = TRUE; - } - break; - case ci_aux_copy: - { - rdp.skip_drawing = FALSE; - if (CloseTextureBuffer(prev_fb.status != ci_aux_copy)) - ; - else if (!rdp.fb_drawn) - { - CopyFrameBuffer (); - rdp.fb_drawn = TRUE; - } - if (fb_hwfbe_enabled) - OpenTextureBuffer(cur_fb); - } - break; - case ci_old_copy: - { - if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) - { - if (cur_fb.width == rdp.ci_width) - { - memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<>1); - } - //rdp.skip_drawing = TRUE; - } - else - { - memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<>1); - } - } - break; - /* - else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i) - { - // CopyFrameBuffer (); - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - rdp.skip_drawing = FALSE; - } - */ - case ci_aux: - { - if (!fb_hwfbe_enabled && cur_fb.format != 0) - rdp.skip_drawing = TRUE; - else - { - rdp.skip_drawing = FALSE; - if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb)) - ; - else - { - if (cur_fb.format != 0) - rdp.skip_drawing = TRUE; - if (rdp.ci_count == 0) - { - // if (rdp.num_of_ci > 1) - // { - rdp.scale_x = 1.0f; - rdp.scale_y = 1.0f; - // } - } - else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) && - (prev_fb.width == cur_fb.width)) // for Pokemon Stadium - CopyFrameBuffer (); - } - } - cur_fb.status = ci_aux; - } - break; - case ci_zimg: - if (settings.ucode != ucode_PerfectDark) - { - if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR))) - { - GrLOD_t LOD = GR_LOD_LOG2_1024; - if (settings.scr_res_x > 1024) - LOD = GR_LOD_LOG2_2048; - grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD, - GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); - grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT ); - LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n"); - } - } - rdp.skip_drawing = TRUE; - break; - case ci_zcopy: - if (settings.ucode != ucode_PerfectDark) - { - if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count) - { - CopyDepthBuffer(); - } - rdp.skip_drawing = TRUE; - } - break; - case ci_useless: - rdp.skip_drawing = TRUE; - break; - case ci_copy_self: - if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) - OpenTextureBuffer(cur_fb); - rdp.skip_drawing = FALSE; - break; - default: - rdp.skip_drawing = FALSE; - } - - if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium - { - if (!fb_hwfbe_enabled && prev_fb.format == 0) - CopyFrameBuffer (); - else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100) - CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); - } - if (!fb_hwfbe_enabled && cur_fb.status == ci_copy) - { - if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) - { - RestoreScale(); - } - } - if (!fb_hwfbe_enabled && cur_fb.status == ci_aux) - { - if (cur_fb.format == 0) - { - if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer - { - int width = cur_fb.width; - int height = cur_fb.height; - wxUint16 *ptr_dst = new wxUint16[width*height]; - wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr); - wxUint16 c; - - for (int y=0; y> 1) | 0x8000; - ptr_dst[x + y * width] = c; - } - } - grLfbWriteRegion(GR_BUFFER_BACKBUFFER, - (wxUint32)rdp.offset_x, - (wxUint32)rdp.offset_y, - GR_LFB_SRC_FMT_555, - width, - height, - FXFALSE, - width<<1, - ptr_dst); - delete[] ptr_dst; - } - /* - else //just clear buffer - { - - grColorMask(FXTRUE, FXTRUE); - grBufferClear (0, 0, 0xFFFF); - } - */ - } - } - - if ((cur_fb.status == ci_main) && (rdp.ci_count > 0)) - { - int to_org_res = TRUE; - for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++) - { - if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy)) - { - to_org_res = FALSE; - break; - } - } - if (to_org_res) - { - LRDP("return to original scale\n"); - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - if (fb_hwfbe_enabled && !rdp.read_whole_frame) - CloseTextureBuffer(); - } - if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index)) - CloseTextureBuffer(); - - } - rdp.ci_status = cur_fb.status; - rdp.ci_count++; - } - - rdp.ocimg = rdp.cimg; - rdp.cimg = segoffset(rdp.cmd1) & BMASK; - rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1; - if (fb_emulation_enabled) - rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height; - else if (rdp.ci_width == 32) - rdp.ci_height = 32; - else - rdp.ci_height = rdp.scissor_o.lr_y; - if (rdp.zimg == rdp.cimg) - { - rdp.zi_width = rdp.ci_width; - // int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height); - // rdp.zi_words = rdp.zi_width * zi_height; - } - wxUint32 format = (rdp.cmd0 >> 21) & 0x7; - rdp.ci_size = (rdp.cmd0 >> 19) & 0x3; - rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1)); - FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size); - FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK); - - if (format != 0) //can't draw into non RGBA buffer - { - if (!rdp.cur_image) - { - if (fb_hwfbe_enabled && rdp.ci_width <= 64) - OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); - else if (format > 2) - rdp.skip_drawing = TRUE; - return; - } - } - else - { - if (!fb_emulation_enabled) - rdp.skip_drawing = FALSE; - } - - CI_SET = TRUE; - if (settings.swapmode > 0) - { - if (rdp.zimg == rdp.cimg) - rdp.updatescreen = 1; - - int viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE; - if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image) - { - if (fb_emulation_enabled) - rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; - else - rdp.maincimg[0].addr = rdp.cimg; - rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr; - swapped_addr = rdp.cimg; - newSwapBuffers(); - rdp.vi_org_reg = *gfx.VI_ORIGIN_REG; - SwapOK = FALSE; - if (fb_hwfbe_enabled) - { - if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg)) - { - int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index; - FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr); - OpenTextureBuffer(rdp.frame_buffers[idx]); - if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave - rdp.copy_ci_index = 0; - } - else if (rdp.read_whole_frame && !rdp.cur_image) - { - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - } - } - } -} - -static void rsp_reserved0() -{ - if (settings.ucode == ucode_DiddyKong) - { - ucode5_texshiftaddr = segoffset(rdp.cmd1); - ucode5_texshiftcount = 0; - FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr); - } - else - { - RDP_E("reserved0 - IGNORED\n"); - LRDP("reserved0 - IGNORED\n"); - } -} - -static void rsp_reserved1() -{ - LRDP("reserved1 - ignored\n"); -} - -static void rsp_reserved2() -{ - LRDP("reserved2\n"); -} - -static void rsp_reserved3() -{ - LRDP("reserved3 - ignored\n"); -} - -void SetWireframeCol () -{ - if (!fullscreen) return; - - switch (settings.wfmode) - { - //case 0: // normal colors, don't do anything - case 1: // vertex colors - grColorCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_ITERATED, - GR_COMBINE_OTHER_NONE, - FXFALSE); - grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_ITERATED, - GR_COMBINE_OTHER_NONE, - FXFALSE); - grAlphaBlendFunction (GR_BLEND_ONE, - GR_BLEND_ZERO, - GR_BLEND_ZERO, - GR_BLEND_ZERO); - grTexCombine (GR_TMU0, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - FXFALSE, FXFALSE); - grTexCombine (GR_TMU1, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - FXFALSE, FXFALSE); - break; - case 2: // red only - grColorCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_CONSTANT, - GR_COMBINE_OTHER_NONE, - FXFALSE); - grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_LOCAL_CONSTANT, - GR_COMBINE_OTHER_NONE, - FXFALSE); - grConstantColorValue (0xFF0000FF); - grAlphaBlendFunction (GR_BLEND_ONE, - GR_BLEND_ZERO, - GR_BLEND_ZERO, - GR_BLEND_ZERO); - grTexCombine (GR_TMU0, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - FXFALSE, FXFALSE); - grTexCombine (GR_TMU1, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - GR_COMBINE_FUNCTION_ZERO, - GR_COMBINE_FACTOR_NONE, - FXFALSE, FXFALSE); - break; - } - - grAlphaTestFunction (GR_CMP_ALWAYS); - grCullMode (GR_CULL_DISABLE); - - rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; -} - -/****************************************************************** -Function: FrameBufferRead -Purpose: This function is called to notify the dll that the -frame buffer memory is beening read at the given address. -DLL should copy content from its render buffer to the frame buffer -in N64 RDRAM -DLL is responsible to maintain its own frame buffer memory addr list -DLL should copy 4KB block content back to RDRAM frame buffer. -Emulator should not call this function again if other memory -is read within the same 4KB range -input: addr rdram address -val val -size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 -output: none -*******************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -EXPORT void CALL FBRead(wxUint32 addr) -{ - LOG ("FBRead ()\n"); - - if (cpu_fb_ignore) - return; - if (cpu_fb_write_called) - { - cpu_fb_ignore = TRUE; - cpu_fb_write = FALSE; - return; - } - cpu_fb_read_called = TRUE; - wxUint32 a = segoffset(addr); - FRDP("FBRead. addr: %08lx\n", a); - if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end)) - { - fbreads_back++; - //if (fbreads_back > 2) //&& (rdp.ci_width <= 320)) - { - CopyFrameBuffer (); - rdp.fb_drawn = TRUE; - } - } - if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2)) - { - fbreads_front++; - //if (fbreads_front > 2)//&& (rdp.ci_width <= 320)) - { - wxUint32 cimg = rdp.cimg; - rdp.cimg = rdp.maincimg[1].addr; - if (fb_emulation_enabled) - { - rdp.ci_width = rdp.maincimg[1].width; - rdp.ci_count = 0; - wxUint32 h = rdp.frame_buffers[0].height; - rdp.frame_buffers[0].height = rdp.maincimg[1].height; - CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); - rdp.frame_buffers[0].height = h; - } - else - { - CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); - } - rdp.cimg = cimg; - rdp.fb_drawn_front = TRUE; - } - } -} - -#if 0 -/****************************************************************** -Function: FrameBufferWriteList -Purpose: This function is called to notify the dll that the -frame buffer has been modified by CPU at the given address. -input: FrameBufferModifyEntry *plist -size = size of the plist, max = 1024 -output: none -*******************************************************************/ -EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size) -{ - LOG ("FBWList ()\n"); - FRDP("FBWList. size: %d\n", size); -} -#endif - -/****************************************************************** -Function: FrameBufferWrite -Purpose: This function is called to notify the dll that the -frame buffer has been modified by CPU at the given address. -input: addr rdram address -val val -size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 -output: none -*******************************************************************/ -EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size) -{ - LOG ("FBWrite ()\n"); - if (cpu_fb_ignore) - return; - if (cpu_fb_read_called) - { - cpu_fb_ignore = TRUE; - cpu_fb_write = FALSE; - return; - } - cpu_fb_write_called = TRUE; - wxUint32 a = segoffset(addr); - FRDP("FBWrite. addr: %08lx\n", a); - if (a < rdp.cimg || a > rdp.ci_end) - return; - cpu_fb_write = TRUE; - wxUint32 shift_l = (a-rdp.cimg) >> 1; - wxUint32 shift_r = shift_l+2; - - d_ul_x = min(d_ul_x, shift_l%rdp.ci_width); - d_ul_y = min(d_ul_y, shift_l/rdp.ci_width); - d_lr_x = max(d_lr_x, shift_r%rdp.ci_width); - d_lr_y = max(d_lr_y, shift_r/rdp.ci_width); -} - - -/************************************************************************ -Function: FBGetFrameBufferInfo -Purpose: This function is called by the emulator core to retrieve frame -buffer information from the video plugin in order to be able -to notify the video plugin about CPU frame buffer read/write -operations - -size: -= 1 byte -= 2 word (16 bit) <-- this is N64 default depth buffer format -= 4 dword (32 bit) - -when frame buffer information is not available yet, set all values -in the FrameBufferInfo structure to 0 - -input: FrameBufferInfo pinfo[6] -pinfo is pointed to a FrameBufferInfo structure which to be -filled in by this function -output: Values are return in the FrameBufferInfo structure -Plugin can return up to 6 frame buffer info -************************************************************************/ -///* -#if 0 -typedef struct -{ - wxUint32 addr; - wxUint32 size; - wxUint32 width; - wxUint32 height; -} FrameBufferInfo; -#endif -EXPORT void CALL FBGetFrameBufferInfo(void *p) -{ - VLOG ("FBGetFrameBufferInfo ()\n"); - FrameBufferInfo * pinfo = (FrameBufferInfo *)p; - memset(pinfo,0,sizeof(FrameBufferInfo)*6); - if (!(settings.frame_buffer&fb_get_info)) - return; - LRDP("FBGetFrameBufferInfo ()\n"); - //* - if (fb_emulation_enabled) - { - pinfo[0].addr = rdp.maincimg[1].addr; - pinfo[0].size = rdp.maincimg[1].size; - pinfo[0].width = rdp.maincimg[1].width; - pinfo[0].height = rdp.maincimg[1].height; - int info_index = 1; - for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++) - { - COLOR_IMAGE & cur_fb = rdp.frame_buffers[i]; - if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self || - cur_fb.status == ci_old_copy) - { - pinfo[info_index].addr = cur_fb.addr; - pinfo[info_index].size = cur_fb.size; - pinfo[info_index].width = cur_fb.width; - pinfo[info_index].height = cur_fb.height; - info_index++; - } - } - } - else - { - pinfo[0].addr = rdp.maincimg[0].addr; - pinfo[0].size = rdp.ci_size; - pinfo[0].width = rdp.ci_width; - pinfo[0].height = rdp.ci_width*3/4; - pinfo[1].addr = rdp.maincimg[1].addr; - pinfo[1].size = rdp.ci_size; - pinfo[1].width = rdp.ci_width; - pinfo[1].height = rdp.ci_width*3/4; - } - //*/ -} -#ifdef __cplusplus -} -#endif -//*/ -#include "ucodeFB.h" - -void DetectFrameBufferUsage () -{ - LRDP("DetectFrameBufferUsage\n"); - - wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); - wxUint32 a; - - int tidal = FALSE; - if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) - tidal = TRUE; - wxUint32 ci = rdp.cimg, zi = rdp.zimg; - wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height; - rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; - rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0; - rdp.zimg_end = 0; - rdp.tmpzimg = 0; - rdp.motionblur = FALSE; - rdp.main_ci_last_tex_addr = 0; - int previous_ci_was_read = rdp.read_previous_ci; - rdp.read_previous_ci = FALSE; - rdp.read_whole_frame = FALSE; - rdp.swap_ci_index = rdp.black_ci_index = -1; - SwapOK = TRUE; - - // Start executing at the start of the display list - rdp.pc_i = 0; - rdp.pc[rdp.pc_i] = dlist_start; - rdp.dl_count = -1; - rdp.halt = 0; - rdp.scale_x_bak = rdp.scale_x; - rdp.scale_y_bak = rdp.scale_y; - - // MAIN PROCESSING LOOP - do { - - // Get the address of the next command - a = rdp.pc[rdp.pc_i] & BMASK; - - // Load the next command and its input - rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / - - // Output the address before the command - - // Go to the next instruction - rdp.pc[rdp.pc_i] = (a+8) & BMASK; - - if (wxPtrToUInt(reinterpret_cast(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))) - gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] (); - - // check DL counter - if (rdp.dl_count != -1) - { - rdp.dl_count --; - if (rdp.dl_count == 0) - { - rdp.dl_count = -1; - - LRDP("End of DL\n"); - rdp.pc_i --; - } - } - - } while (!rdp.halt); - SwapOK = TRUE; - if (rdp.ci_count > NUMTEXBUF) //overflow - { - rdp.cimg = ci; - rdp.zimg = zi; - rdp.num_of_ci = rdp.ci_count; - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - return; - } - - if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index) - rdp.frame_buffers[rdp.black_ci_index].status = ci_main; - - if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) - { - if (rdp.ci_count > 1) - rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; - else - rdp.frame_buffers[rdp.ci_count-1].status = ci_main; - } - - if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) && - (rdp.frame_buffers[rdp.main_ci_index].width < 320) && - (rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width)) - { - for (int i = 0; i < rdp.ci_count; i++) - { - if (rdp.frame_buffers[i].status == ci_main) - rdp.frame_buffers[i].status = ci_aux; - else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr) - rdp.frame_buffers[i].status = ci_main; - // FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status); - } - rdp.main_ci_index = rdp.ci_count-1; - } - - int all_zimg = TRUE; - int i; - for (i = 0; i < rdp.ci_count; i++) - { - if (rdp.frame_buffers[i].status != ci_zimg) - { - all_zimg = FALSE; - break; - } - } - if (all_zimg) - { - for (i = 0; i < rdp.ci_count; i++) - rdp.frame_buffers[i].status = ci_main; - } - - LRDP("detect fb final results: \n"); - for (i = 0; i < rdp.ci_count; i++) - { - FRDP("rdp.frame_buffers[%d].status = %s, addr: %08lx, height: %d\n", i, CIStatus[rdp.frame_buffers[i].status], rdp.frame_buffers[i].addr, rdp.frame_buffers[i].height); - } - - rdp.cimg = ci; - rdp.zimg = zi; - rdp.num_of_ci = rdp.ci_count; - if (rdp.read_previous_ci && previous_ci_was_read) - { - if (!fb_hwfbe_enabled || !rdp.copy_ci_index) - rdp.motionblur = TRUE; - } - if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy)) - { - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - } - - if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index) - rdp.read_whole_frame = TRUE; - if (rdp.read_whole_frame) - { - if (fb_hwfbe_enabled) - { - if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark)) - { - int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; - wxUint32 height = rdp.frame_buffers[ind].height; - rdp.frame_buffers[ind].height = ci_height; - CopyFrameBuffer(); - rdp.frame_buffers[ind].height = height; - } - if (rdp.swap_ci_index < 0) - { - rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE; - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - } - else - { - if (rdp.motionblur) - { - if (settings.frame_buffer&fb_motionblur) - CopyFrameBuffer(); - else - memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); - } - else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width) - { - if (rdp.maincimg[0].height > 65) //for 1080 - { - rdp.cimg = rdp.maincimg[0].addr; - rdp.ci_width = rdp.maincimg[0].width; - rdp.ci_count = 0; - wxUint32 h = rdp.frame_buffers[0].height; - rdp.frame_buffers[0].height = rdp.maincimg[0].height; - CopyFrameBuffer(); - rdp.frame_buffers[0].height = h; - } - else //conker - { - CopyFrameBuffer(); - } - } - } - } - - if (fb_hwfbe_enabled) - { - for (i = 0; i < voodoo.num_tmu; i++) - { - rdp.texbufs[i].clear_allowed = TRUE; - for (int j = 0; j < 256; j++) - { - rdp.texbufs[i].images[j].drawn = FALSE; - rdp.texbufs[i].images[j].clear = TRUE; - } - } - if (tidal) - { - //LRDP("Tidal wave!\n"); - rdp.copy_ci_index = rdp.main_ci_index; - } - } - rdp.ci_count = 0; - if (settings.hacks&hack_Banjo2) - rdp.cur_tex_buf = 0; - rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; - // rdp.scale_x = rdp.scale_x_bak; - // rdp.scale_y = rdp.scale_y_bak; - LRDP("DetectFrameBufferUsage End\n"); -} - -/******************************************* - * ProcessRDPList * - ******************************************* - * based on sources of ziggy's z64 * - *******************************************/ - -static wxUint32 rdp_cmd_ptr = 0; -static wxUint32 rdp_cmd_cur = 0; -static wxUint32 rdp_cmd_data[0x1000]; - -void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer, - wxUint32 * rdp_cmd) -{ - rdp.cur_tile = (w1 >> 16) & 0x7; - int j; - int xleft, xright, xleft_inc, xright_inc; - int r, g, b, a, z, s, t, w; - int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0; - int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0; - int flip = (w1 & 0x800000) ? 1 : 0; - - wxInt32 yl, ym, yh; - wxInt32 xl, xm, xh; - wxInt32 dxldy, dxhdy, dxmdy; - wxUint32 w3, w4, w5, w6, w7, w8; - - wxUint32 * shade_base = rdp_cmd + 8; - wxUint32 * texture_base = rdp_cmd + 8; - wxUint32 * zbuffer_base = rdp_cmd + 8; - - if (shade) - { - texture_base += 16; - zbuffer_base += 16; - } - if (texture) - { - zbuffer_base += 16; - } - - w3 = rdp_cmd[2]; - w4 = rdp_cmd[3]; - w5 = rdp_cmd[4]; - w6 = rdp_cmd[5]; - w7 = rdp_cmd[6]; - w8 = rdp_cmd[7]; - - yl = (w1 & 0x3fff); - ym = ((w2 >> 16) & 0x3fff); - yh = ((w2 >> 0) & 0x3fff); - xl = (wxInt32)(w3); - xh = (wxInt32)(w5); - xm = (wxInt32)(w7); - dxldy = (wxInt32)(w4); - dxhdy = (wxInt32)(w6); - dxmdy = (wxInt32)(w8); - - if (yl & (0x800<<2)) yl |= 0xfffff000<<2; - if (ym & (0x800<<2)) ym |= 0xfffff000<<2; - if (yh & (0x800<<2)) yh |= 0xfffff000<<2; - - yh &= ~3; - - r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000; - - if (shade) - { - r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff); - g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff); - b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff); - a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff); - drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff); - dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff); - dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff); - dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff); - drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff); - dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff); - dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff); - dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff); - } - if (texture) - { - s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff); - t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff); - w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff); - // w = abs(w); - dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff); - dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff); - dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff); - dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff); - dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff); - dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff); - } - if (zbuffer) - { - z = zbuffer_base[0]; - dzdx = zbuffer_base[1]; - dzde = zbuffer_base[2]; - } - - xh <<= 2; xm <<= 2; xl <<= 2; - r <<= 2; g <<= 2; b <<= 2; a <<= 2; - dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2; - dzdx >>= 2; dzde >>= 2; - dwdx >>= 2; dwde >>= 2; - -#define XSCALE(x) (float(x)/(1<<18)) -#define YSCALE(y) (float(y)/(1<<2)) -#define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000) - //#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f) - //#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f) -#define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f) -#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18) -#define _PERSP(w) ( w ) -#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) ) -#define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21)) -#define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21)) - - int nbVtxs = 0; - VERTEX vtxbuf[12]; - VERTEX * vtx = &vtxbuf[nbVtxs++]; - - xleft = xm; - xright = xh; - xleft_inc = dxmdy; - xright_inc = dxhdy; - - while (yh xright-0x10000))) { - xleft += xleft_inc; - xright += xright_inc; - s += dsde; t += dtde; w += dwde; - r += drde; g += dgde; b += dbde; a += dade; - z += dzde; - yh++; - } - - j = ym-yh; - if (j > 0) - { - int dx = (xleft-xright)>>16; - if ((!flip && xleft < xright) || - (flip/* && xleft > xright*/)) - { - if (shade) { - vtx->r = CSCALE(r+drdx*dx); - vtx->g = CSCALE(g+dgdx*dx); - vtx->b = CSCALE(b+dbdx*dx); - vtx->a = CSCALE(a+dadx*dx); - } - if (texture) { - vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); - vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); - } - vtx->x = XSCALE(xleft); - vtx->y = YSCALE(yh); - vtx->z = ZSCALE(z+dzdx*dx); - vtx->w = WSCALE(w+dwdx*dx); - vtx = &vtxbuf[nbVtxs++]; - } - if ((!flip/* && xleft < xright*/) || - (flip && xleft > xright)) - { - if (shade) { - vtx->r = CSCALE(r); - vtx->g = CSCALE(g); - vtx->b = CSCALE(b); - vtx->a = CSCALE(a); - } - if (texture) { - vtx->ou = SSCALE(s, w); - vtx->ov = TSCALE(t, w); - } - vtx->x = XSCALE(xright); - vtx->y = YSCALE(yh); - vtx->z = ZSCALE(z); - vtx->w = WSCALE(w); - vtx = &vtxbuf[nbVtxs++]; - } - xleft += xleft_inc*j; xright += xright_inc*j; - s += dsde*j; t += dtde*j; - if (w + dwde*j) w += dwde*j; - else w += dwde*(j-1); - r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; - z += dzde*j; - // render ... - } - - if (xl != xh) - xleft = xl; - - //if (yl-ym > 0) - { - int dx = (xleft-xright)>>16; - if ((!flip && xleft <= xright) || - (flip/* && xleft >= xright*/)) - { - if (shade) { - vtx->r = CSCALE(r+drdx*dx); - vtx->g = CSCALE(g+dgdx*dx); - vtx->b = CSCALE(b+dbdx*dx); - vtx->a = CSCALE(a+dadx*dx); - } - if (texture) { - vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); - vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); - } - vtx->x = XSCALE(xleft); - vtx->y = YSCALE(ym); - vtx->z = ZSCALE(z+dzdx*dx); - vtx->w = WSCALE(w+dwdx*dx); - vtx = &vtxbuf[nbVtxs++]; - } - if ((!flip/* && xleft <= xright*/) || - (flip && xleft >= xright)) - { - if (shade) { - vtx->r = CSCALE(r); - vtx->g = CSCALE(g); - vtx->b = CSCALE(b); - vtx->a = CSCALE(a); - } - if (texture) { - vtx->ou = SSCALE(s, w); - vtx->ov = TSCALE(t, w); - } - vtx->x = XSCALE(xright); - vtx->y = YSCALE(ym); - vtx->z = ZSCALE(z); - vtx->w = WSCALE(w); - vtx = &vtxbuf[nbVtxs++]; - } - } - xleft_inc = dxldy; - xright_inc = dxhdy; - - j = yl-ym; - //j--; // ? - xleft += xleft_inc*j; xright += xright_inc*j; - s += dsde*j; t += dtde*j; w += dwde*j; - r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; - z += dzde*j; - - while (yl>ym && - !((!flip && xleft < xright+0x10000) || - (flip && xleft > xright-0x10000))) { - xleft -= xleft_inc; xright -= xright_inc; - s -= dsde; t -= dtde; w -= dwde; - r -= drde; g -= dgde; b -= dbde; a -= dade; - z -= dzde; - j--; - yl--; - } - - // render ... - if (j >= 0) { - int dx = (xleft-xright)>>16; - if ((!flip && xleft <= xright) || - (flip/* && xleft >= xright*/)) - { - if (shade) { - vtx->r = CSCALE(r+drdx*dx); - vtx->g = CSCALE(g+dgdx*dx); - vtx->b = CSCALE(b+dbdx*dx); - vtx->a = CSCALE(a+dadx*dx); - } - if (texture) { - vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); - vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); - } - vtx->x = XSCALE(xleft); - vtx->y = YSCALE(yl); - vtx->z = ZSCALE(z+dzdx*dx); - vtx->w = WSCALE(w+dwdx*dx); - vtx = &vtxbuf[nbVtxs++]; - } - if ((!flip/* && xleft <= xright*/) || - (flip && xleft >= xright)) - { - if (shade) { - vtx->r = CSCALE(r); - vtx->g = CSCALE(g); - vtx->b = CSCALE(b); - vtx->a = CSCALE(a); - } - if (texture) { - vtx->ou = SSCALE(s, w); - vtx->ov = TSCALE(t, w); - } - vtx->x = XSCALE(xright); - vtx->y = YSCALE(yl); - vtx->z = ZSCALE(z); - vtx->w = WSCALE(w); - vtx = &vtxbuf[nbVtxs++]; - } - } - - if (fullscreen) - { - update (); - for (int k = 0; k < nbVtxs-1; k++) - { - VERTEX * v = &vtxbuf[k]; - v->x = v->x * rdp.scale_x + rdp.offset_x; - v->y = v->y * rdp.scale_y + rdp.offset_y; - // v->z = 1.0f;///v->w; - v->q = 1.0f/v->w; - v->u1 = v->u0 = v->ou; - v->v1 = v->v0 = v->ov; - if (rdp.tex >= 1 && rdp.cur_cache[0]) - { - if (rdp.tiles[rdp.cur_tile].shift_s) - { - if (rdp.tiles[rdp.cur_tile].shift_s > 10) - v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); - else - v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s); - } - if (rdp.tiles[rdp.cur_tile].shift_t) - { - if (rdp.tiles[rdp.cur_tile].shift_t > 10) - v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); - else - v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t); - } - - v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; - v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; - v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0; - v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0; - v->u0 /= v->w; - v->v0 /= v->w; - } - - if (rdp.tex >= 2 && rdp.cur_cache[1]) - { - if (rdp.tiles[rdp.cur_tile+1].shift_s) - { - if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) - v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); - else - v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s); - } - if (rdp.tiles[rdp.cur_tile+1].shift_t) - { - if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) - v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); - else - v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t); - } - - v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; - v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; - v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1; - v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1; - v->u1 /= v->w; - v->v1 /= v->w; - } - apply_shade_mods (v); - } - ConvertCoordsConvert (vtxbuf, nbVtxs); - grCullMode (GR_CULL_DISABLE); - grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX)); - if (_debugger.capture) - { - VERTEX vl[3]; - vl[0] = vtxbuf[0]; - vl[1] = vtxbuf[2]; - vl[2] = vtxbuf[1]; - add_tri (vl, 3, TRI_TRIANGLE); - rdp.tri_n++; - if (nbVtxs > 4) - { - vl[0] = vtxbuf[2]; - vl[1] = vtxbuf[3]; - vl[2] = vtxbuf[1]; - add_tri (vl, 3, TRI_TRIANGLE); - rdp.tri_n++; - } - } - } -} - -static void rdp_triangle(int shade, int texture, int zbuffer) -{ - lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur); -} - -static void rdp_trifill() -{ - rdp_triangle(0, 0, 0); - LRDP("trifill\n"); -} - -static void rdp_trishade() -{ - rdp_triangle(1, 0, 0); - LRDP("trishade\n"); -} - -static void rdp_tritxtr() -{ - rdp_triangle(0, 1, 0); - LRDP("tritxtr\n"); -} - -static void rdp_trishadetxtr() -{ - rdp_triangle(1, 1, 0); - LRDP("trishadetxtr\n"); -} - -static void rdp_trifillz() -{ - rdp_triangle(0, 0, 1); - LRDP("trifillz\n"); -} - -static void rdp_trishadez() -{ - rdp_triangle(1, 0, 1); - LRDP("trishadez\n"); -} - -static void rdp_tritxtrz() -{ - rdp_triangle(0, 1, 1); - LRDP("tritxtrz\n"); -} - -static void rdp_trishadetxtrz() -{ - rdp_triangle(1, 1, 1); - LRDP("trishadetxtrz\n"); -} - - -static rdp_instr rdp_command_table[64] = -{ - /* 0x00 */ - spnoop, undef, undef, undef, - undef, undef, undef, undef, - rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, - rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, - /* 0x10 */ - undef, undef, undef, undef, - undef, undef, undef, undef, - undef, undef, undef, undef, - undef, undef, undef, undef, - /* 0x20 */ - undef, undef, undef, undef, - rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, - rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, - rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, - /* 0x30 */ - rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, - rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, - rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, - rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage -}; - -static const wxUint32 rdp_command_length[64] = -{ - 8, // 0x00, No Op - 8, // 0x01, ??? - 8, // 0x02, ??? - 8, // 0x03, ??? - 8, // 0x04, ??? - 8, // 0x05, ??? - 8, // 0x06, ??? - 8, // 0x07, ??? - 32, // 0x08, Non-Shaded Triangle - 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle - 32+64, // 0x0a, Textured Triangle - 32+64+16, // 0x0b, Textured, Z-Buffered Triangle - 32+64, // 0x0c, Shaded Triangle - 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle - 32+64+64, // 0x0e, Shaded+Textured Triangle - 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle - 8, // 0x10, ??? - 8, // 0x11, ??? - 8, // 0x12, ??? - 8, // 0x13, ??? - 8, // 0x14, ??? - 8, // 0x15, ??? - 8, // 0x16, ??? - 8, // 0x17, ??? - 8, // 0x18, ??? - 8, // 0x19, ??? - 8, // 0x1a, ??? - 8, // 0x1b, ??? - 8, // 0x1c, ??? - 8, // 0x1d, ??? - 8, // 0x1e, ??? - 8, // 0x1f, ??? - 8, // 0x20, ??? - 8, // 0x21, ??? - 8, // 0x22, ??? - 8, // 0x23, ??? - 16, // 0x24, Texture_Rectangle - 16, // 0x25, Texture_Rectangle_Flip - 8, // 0x26, Sync_Load - 8, // 0x27, Sync_Pipe - 8, // 0x28, Sync_Tile - 8, // 0x29, Sync_Full - 8, // 0x2a, Set_Key_GB - 8, // 0x2b, Set_Key_R - 8, // 0x2c, Set_Convert - 8, // 0x2d, Set_Scissor - 8, // 0x2e, Set_Prim_Depth - 8, // 0x2f, Set_Other_Modes - 8, // 0x30, Load_TLUT - 8, // 0x31, ??? - 8, // 0x32, Set_Tile_Size - 8, // 0x33, Load_Block - 8, // 0x34, Load_Tile - 8, // 0x35, Set_Tile - 8, // 0x36, Fill_Rectangle - 8, // 0x37, Set_Fill_Color - 8, // 0x38, Set_Fog_Color - 8, // 0x39, Set_Blend_Color - 8, // 0x3a, Set_Prim_Color - 8, // 0x3b, Set_Env_Color - 8, // 0x3c, Set_Combine - 8, // 0x3d, Set_Texture_Image - 8, // 0x3e, Set_Mask_Image - 8 // 0x3f, Set_Color_Image -}; - -#define rdram ((wxUint32*)gfx.RDRAM) -#define rsp_dmem ((wxUint32*)gfx.DMEM) - -#define dp_start (*(wxUint32*)gfx.DPC_START_REG) -#define dp_end (*(wxUint32*)gfx.DPC_END_REG) -#define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG) -#define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG) - -inline wxUint32 READ_RDP_DATA(wxUint32 address) -{ - if (dp_status & 0x1) // XBUS_DMEM_DMA enabled - return rsp_dmem[(address & 0xfff)>>2]; - else - return rdram[address>>2]; -} - -static void rdphalf_1() -{ - wxUint32 cmd = rdp.cmd1 >> 24; - if (cmd >= 0xc8 && cmd <=0xcf) //triangle command - { - LRDP("rdphalf_1 - lle triangle\n"); - rdp_cmd_ptr = 0; - rdp_cmd_cur = 0; - wxUint32 a; - - do - { - rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; - // check DL counter - if (rdp.dl_count != -1) - { - rdp.dl_count --; - if (rdp.dl_count == 0) - { - rdp.dl_count = -1; - - LRDP("End of DL\n"); - rdp.pc_i --; - } - } - - // Get the address of the next command - a = rdp.pc[rdp.pc_i] & BMASK; - - // Load the next command and its input - rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / - - // Go to the next instruction - rdp.pc[rdp.pc_i] = (a+8) & BMASK; - - }while ((rdp.cmd0 >> 24) != 0xb3); - rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; - cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; - rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; - rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; - /* - wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2]; - if ((cmd3>>24) == 0xb4) - rglSingleTriangle = TRUE; - else - rglSingleTriangle = FALSE; - */ - rdp_command_table[cmd](); - } - else - { - LRDP("rdphalf_1 - IGNORED\n"); - } -} - -static void rdphalf_2() -{ - RDP_E("rdphalf_2 - IGNORED\n"); - LRDP("rdphalf_2 - IGNORED\n"); -} - -static void rdphalf_cont() -{ - RDP_E("rdphalf_cont - IGNORED\n"); - LRDP("rdphalf_cont - IGNORED\n"); -} - -/****************************************************************** -Function: ProcessRDPList -Purpose: This function is called when there is a Dlist to be -processed. (Low level GFX list) -input: none -output: none -*******************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif -EXPORT void CALL ProcessRDPList(void) -{ - LOG ("ProcessRDPList ()\n"); - LRDP("ProcessRDPList ()\n"); - - SoftLocker lock(mutexProcessDList); - if (!lock.IsOk()) //mutex is busy - { - if (!fullscreen) - drawNoFullscreenMessage(); - // Set an interrupt to allow the game to continue - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - return; - } - - wxUint32 i; - wxUint32 cmd, length, cmd_length; - rdp_cmd_ptr = 0; - rdp_cmd_cur = 0; - - if (dp_end <= dp_current) return; - length = dp_end - dp_current; - - // load command data - for (i=0; i < length; i += 4) - { - rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i); - if (rdp_cmd_ptr >= 0x1000) - { - FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end); - } - } - - dp_current = dp_end; - - cmd = (rdp_cmd_data[0] >> 24) & 0x3f; - cmd_length = (rdp_cmd_ptr + 1) * 4; - - // check if more data is needed - if (cmd_length < rdp_command_length[cmd]) - return; - rdp.LLE = TRUE; - while (rdp_cmd_cur < rdp_cmd_ptr) - { - cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; - - if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd]) - return; - - // execute the command - rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; - rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; - rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2]; - rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3]; - rdp_command_table[cmd](); - - rdp_cmd_cur += rdp_command_length[cmd] / 4; - }; - rdp.LLE = FALSE; - - dp_start = dp_end; - - dp_status &= ~0x0002; - - //} -} - -#ifdef __cplusplus -} -#endif - +} + +void microcheck () +{ + wxUint32 i; + uc_crc = 0; + + // Check first 3k of ucode, because the last 1k sometimes contains trash + for (i=0; i<3072>>2; i++) + { + uc_crc += ((wxUint32*)microcode)[i]; + } + + FRDP_E ("crc: %08lx\n", uc_crc); + +#ifdef LOG_UCODE + std::ofstream ucf; + ucf.open ("ucode.txt", std::ios::out | std::ios::binary); + char d; + for (i=0; i<0x400000; i++) + { + d = ((char*)gfx.RDRAM)[i^3]; + ucf.write (&d, 1); + } + ucf.close (); +#endif + + FRDP("ucode = %08lx\n", uc_crc); + + int uc = LookupUcode(uc_crc); + + if (uc == -2 && ucode_error_report) + { + settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE); + + ReleaseGfx (); + ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc); + + ucode_error_report = FALSE; // don't report any more ucode errors from this game + } + else if (uc == -1 && ucode_error_report) + { + settings.ucode = 2; //ini->Read(_T("/SETTINGS/ucode"), 0); + + ReleaseGfx (); + ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc); + + ucode_error_report = FALSE; // don't report any more ucode errors from this game + } + else + { + old_ucode = settings.ucode; + settings.ucode = uc; + FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc); + if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented + { + rdp.Persp_en = 1; + rdp.persp_supported = FALSE; + } + else if (settings.texture_correction) + rdp.persp_supported = TRUE; + } +} + +#ifdef __WINDOWS__ +static void GetClientSize(int * width, int * height) +{ +#ifdef __WINDOWS__ + RECT win_rect; + GetClientRect (gfx.hWnd, &win_rect); + *width = win_rect.right; + *height = win_rect.bottom; +#else + GFXWindow->GetClientSize(width, height); +#endif +} +#endif + +void drawNoFullscreenMessage() +{ +//need to find, how to do it on non-windows OS +//the code below will compile on any OS +//but it works only on windows, because +//I don't know, how to initialize GFXWindow on other OS +#ifdef __WINDOWS__ + LOG ("drawNoFullscreenMessage ()\n"); + if (rdp.window_changed) + { + rdp.window_changed = FALSE; + int width, height; + GetClientSize(&width, &height); + + wxClientDC dc(GFXWindow); + dc.SetBrush(*wxMEDIUM_GREY_BRUSH); + dc.SetTextForeground(*wxWHITE); + dc.SetBackgroundMode(wxTRANSPARENT); + dc.DrawRectangle(0, 0, width, height); + + wxCoord w, h; + wxString text = wxT("Glide64mk2"); + dc.GetTextExtent(text, &w, &h); + wxCoord x = (width - w)/2; + wxCoord y = height/2 - h*4; + dc.DrawText(text, x, y); + + text = wxT("Gfx cannot be drawn in windowed mode"); + dc.GetTextExtent(text, &w, &h); + x = (width - w)/2; + y = height/2 - h; + dc.DrawText(text, x, y); + + text = wxT("Press Alt+Enter to switch to fullscreen"); + dc.GetTextExtent(text, &w, &h); + x = (width - w)/2; + y = (height - h)/2 + h*2; + dc.DrawText(text, x, y); + } +#endif +} + +static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y; + +static void DrawPartFrameBufferToScreen() +{ + FB_TO_SCREEN_INFO fb_info; + fb_info.addr = rdp.cimg; + fb_info.size = rdp.ci_size; + fb_info.width = rdp.ci_width; + fb_info.height = rdp.ci_height; + fb_info.ul_x = d_ul_x; + fb_info.lr_x = d_lr_x; + fb_info.ul_y = d_ul_y; + fb_info.lr_y = d_lr_y; + fb_info.opaque = 0; + DrawFrameBufferToScreen(fb_info); + memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<>1); +} + +#define RGBA16TO32(color) \ + ((color&1)?0xFF:0) | \ + ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ + ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ + ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8) + +static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER) +{ + if (!fullscreen) + return; + FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg); + + // don't bother to write the stuff in asm... the slow part is the read from video card, + // not the copy. + + wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG; + wxUint32 height; + if (fb_emulation_enabled && !(settings.hacks&hack_PPL)) + { + int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; + height = rdp.frame_buffers[ind].height; + } + else + { + height = rdp.ci_lower_bound; + if (settings.hacks&hack_PPL) + height -= rdp.ci_upper_bound; + } + FRDP ("width: %d, height: %d... ", width, height); + + if (rdp.scale_x < 1.1f) + { + wxUint16 * ptr_src = new wxUint16[width*height]; + if (grLfbReadRegion(buffer, + (wxUint32)rdp.offset_x, + (wxUint32)rdp.offset_y,//rdp.ci_upper_bound, + width, + height, + width<<1, + ptr_src)) + { + wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); + wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); + wxUint16 c; + + for (wxUint32 y=0; y 0) + c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; + } + else + { + c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; + } + if (rdp.ci_size == 2) + ptr_dst[(x + y * width)^1] = c; + else + ptr_dst32[x + y * width] = RGBA16TO32(c); + } + } + LRDP("ReadRegion. Framebuffer copy complete.\n"); + } + else + { + LRDP("Framebuffer copy failed.\n"); + } + delete[] ptr_src; + } + else + { + if (rdp.motionblur && fb_hwfbe_enabled) + { + return; + } + else + { + float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f) / max(width, rdp.vi_width); + float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height); + + FRDP("width: %d, height: %d, ul_y: %d, lr_y: %d, scale_x: %f, scale_y: %f, ci_width: %d, ci_height: %d\n",width, height, rdp.ci_upper_bound, rdp.ci_lower_bound, scale_x, scale_y, rdp.ci_width, rdp.ci_height); + GrLfbInfo_t info; + info.size = sizeof(GrLfbInfo_t); + + if (grLfbLock (GR_LFB_READ_ONLY, + buffer, + GR_LFBWRITEMODE_565, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) + { + wxUint16 *ptr_src = (wxUint16*)info.lfbPtr; + wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); + wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); + wxUint16 c; + wxUint32 stride = info.strideInBytes>>1; + + int read_alpha = settings.frame_buffer & fb_read_alpha; + if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) + read_alpha = FALSE; + int x_start = 0, y_start = 0, x_end = width, y_end = height; + if (settings.hacks&hack_BAR) + { + x_start = 80, y_start = 24, x_end = 240, y_end = 86; + } + for (int y=y_start; y 0) + SwapOK = TRUE; + rdp.updatescreen = 1; + + rdp.tri_n = 0; // 0 triangles so far this frame + rdp.debug_n = 0; + + rdp.model_i = 0; // 0 matrices so far in stack + //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin! + rdp.model_stack_size = min(32, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6); + if (rdp.model_stack_size == 0) + rdp.model_stack_size = 32; + rdp.Persp_en = TRUE; + rdp.fb_drawn = rdp.fb_drawn_front = FALSE; + rdp.update = 0x7FFFFFFF; // All but clear cache + rdp.geom_mode = 0; + rdp.acmp = 0; + rdp.maincimg[1] = rdp.maincimg[0]; + rdp.skip_drawing = FALSE; + rdp.s2dex_tex_loaded = FALSE; + rdp.bg_image_height = 0xFFFF; + fbreads_front = fbreads_back = 0; + rdp.fog_multiplier = rdp.fog_offset = 0; + rdp.zsrc = 0; + if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG) + rdp.tlut_mode = 0; //is it correct? + rdp.scissor_set = FALSE; + ucode5_texshiftaddr = ucode5_texshiftcount = 0; + cpu_fb_write = FALSE; + cpu_fb_read_called = FALSE; + cpu_fb_write_called = FALSE; + cpu_fb_ignore = FALSE; + d_ul_x = 0xffff; + d_ul_y = 0xffff; + d_lr_x = 0; + d_lr_y = 0; + depth_buffer_fog = TRUE; + + //analize possible frame buffer usage + if (fb_emulation_enabled) + DetectFrameBufferUsage(); + if (!(settings.hacks&hack_Lego) || rdp.num_of_ci > 1) + rdp.last_bg = 0; + //* End of set states *// + + // Get the start of the display list and the length of it + wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); + wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4); + FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length, (*gfx.VI_X_SCALE_REG & 0xFFF)/1024.0f, (*gfx.VI_Y_SCALE_REG & 0xFFF)/1024.0f); + FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); + + if (cpu_fb_write == TRUE) + DrawPartFrameBufferToScreen(); + if ((settings.hacks&hack_Tonic) && dlist_length < 16) + { + rdp_fullsync(); + FRDP_E("DLIST is too short!\n"); + return; + } + + // Start executing at the start of the display list + rdp.pc_i = 0; + rdp.pc[rdp.pc_i] = dlist_start; + rdp.dl_count = -1; + rdp.halt = 0; + wxUint32 a; + + // catches exceptions so that it doesn't freeze +#ifdef CATCH_EXCEPTIONS + try { +#endif + if (settings.ucode == ucode_Turbo3d) + { + Turbo3D(); + } + else + { + // MAIN PROCESSING LOOP + do { + + // Get the address of the next command + a = rdp.pc[rdp.pc_i] & BMASK; + + // Load the next command and its input + rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / + // cmd2 and cmd3 are filled only when needed, by the function that needs them + + // Output the address before the command +#ifdef LOG_COMMANDS + FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1); +#else + FRDP ("%08lx: ", a); +#endif + + // Go to the next instruction + rdp.pc[rdp.pc_i] = (a+8) & BMASK; + +#ifdef PERFORMANCE + perf_cur = wxDateTime::UNow(); +#endif + // Process this instruction + gfx_instruction[settings.ucode][rdp.cmd0>>24] (); + + // check DL counter + if (rdp.dl_count != -1) + { + rdp.dl_count --; + if (rdp.dl_count == 0) + { + rdp.dl_count = -1; + + LRDP("End of DL\n"); + rdp.pc_i --; + } + } + +#ifdef PERFORMANCE + perf_next = wxDateTime::UNow(); + sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, (perf_next-perf_cur).Format(_T("%l")).mb_str()); + rdp_log << out_buf; +#endif + + } while (!rdp.halt); + } +#ifdef CATCH_EXCEPTIONS + } catch (...) { + + if (fullscreen) + { + ReleaseGfx (); + rdp_reset (); +#ifdef TEXTURE_FILTER + if (settings.ghq_use) + { + ext_ghq_shutdown(); + settings.ghq_use = 0; + } +#endif + } + ERRLOG("The GFX plugin caused an exception and has been disabled."); + exception = TRUE; + return; + } +#endif + + if (fb_emulation_enabled) + { + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + } + if (settings.frame_buffer & fb_ref) + CopyFrameBuffer (); + if (rdp.cur_image) + CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0)); + + if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) + { + newSwapBuffers (); + CI_SET = FALSE; + } + LRDP("ProcessDList end\n"); +} + +#ifdef __cplusplus +} +#endif + +// undef - undefined instruction, always ignore +static void undef() +{ + FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0); + FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0); +#ifdef _ENDUSER_RELEASE_ + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + rdp.halt = 1; +#endif +} + +// spnoop - no operation, always ignore +static void spnoop() +{ + LRDP("spnoop\n"); +} + +// noop - no operation, always ignore +static void rdp_noop() +{ + LRDP("noop\n"); +} + +static void ys_memrect () +{ + wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); + + wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14); + wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2); + wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); + wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2); + + if (lr_y > rdp.scissor_o.lr_y) + lr_y = rdp.scissor_o.lr_y; + wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5; + wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5; + + FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); + if (off_x > 0) + FRDP (" off_x: %d", off_x); + if (off_y > 0) + FRDP (" off_y: %d", off_y); + LRDP("\n"); + + wxUint32 y, width = lr_x - ul_x; + wxUint32 tex_width = rdp.tiles[tile].line << 3; + wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x; + wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x; + + for (y = ul_y; y < lr_y; y++) { + wxUint8 *src = texaddr + (y - ul_y) * tex_width; + wxUint8 *dst = fbaddr + y * rdp.ci_width; + memcpy (dst, src, width); + } +} + +static void pm_palette_mod () +{ + wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); + wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); + wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); + wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1); + wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); + wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); + wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); + wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); + wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); + for (int i = 0; i < 16; i++) + { + dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; + } + LRDP("Texrect palette modification\n"); +} + +static void pd_zcopy () +{ + wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); + wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1; + wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1; + wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); + wxUint16 width = lr_x - ul_x; + wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u; + wxUint16 c; + for (wxUint16 x=0; x> 8); + ptr_dst[(ul_x+x)^1] = c; + // FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c); + } +} + +static void DrawDepthBufferFog() +{ + if (rdp.zi_width < 200) + return; + FB_TO_SCREEN_INFO fb_info; + fb_info.addr = rdp.zimg; + fb_info.size = 2; + fb_info.width = rdp.zi_width; + fb_info.height = rdp.ci_height; + fb_info.ul_x = rdp.scissor_o.ul_x; + fb_info.lr_x = rdp.scissor_o.lr_x; + fb_info.ul_y = rdp.scissor_o.ul_y; + fb_info.lr_y = rdp.scissor_o.lr_y; + fb_info.opaque = 0; + DrawDepthBufferToScreen(fb_info); +} + +static void rdp_texrect() +{ + if (!rdp.LLE) + { + wxUint32 a = rdp.pc[rdp.pc_i]; + wxUint8 cmdHalf1 = gfx.RDRAM[a+3]; + wxUint8 cmdHalf2 = gfx.RDRAM[a+11]; + a >>= 2; + if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2)) + { + //gSPTextureRectangle + rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1]; + rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3]; + rdp.pc[rdp.pc_i] += 16; + } + else + { + //gDPTextureRectangle + if (settings.hacks&hack_ASB) + rdp.cmd2 = 0; + else + rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0]; + rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1]; + rdp.pc[rdp.pc_i] += 8; + } + } + if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX) + { + ys_memrect(); + return; + } + + if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg))) + { + if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless) + { + pm_palette_mod (); + } + else + { + LRDP("Texrect skipped\n"); + } + return; + } + + if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format) + { + //FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1].addr, rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size); + LRDP("Shadow texrect is skipped.\n"); + rdp.tri_n += 2; + return; + } + + if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy)) + { + pd_zcopy (); + LRDP("Depth buffer copied.\n"); + rdp.tri_n += 2; + return; + } + + if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog + { + if (!depth_buffer_fog) + return; + if (settings.fog) + DrawDepthBufferFog(); + depth_buffer_fog = FALSE; + return; + } + + // FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2); + + float ul_x, ul_y, lr_x, lr_y; + if (rdp.cycle_mode == 2) + { + ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14)); + ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2)); + lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14)); + lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2)); + } + else + { + ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f); + ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f); + lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f); + lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f); + } + + if (ul_x >= lr_x) + { + FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x); + return; + } + + if (rdp.cycle_mode > 1) + { + lr_x += 1.0f; + lr_y += 1.0f; + } else if (lr_y - ul_y < 1.0f) + lr_y = ceil(lr_y); + + if (settings.increase_texrect_edge) + { + if (floor(lr_x) != lr_x) + lr_x = ceil(lr_x); + if (floor(lr_y) != lr_y) + lr_y = ceil(lr_y); + } + + //* + if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect)) + { + LRDP("Attempt to optimize texrect\n"); + if (!rdp.tbuff_tex->drawn) + { + DRAWIMAGE d; + d.imageX = 0; + d.imageW = (wxUint16)rdp.tbuff_tex->width; + d.frameX = (wxUint16)ul_x; + d.frameW = (wxUint16)(rdp.tbuff_tex->width); + + d.imageY = 0; + d.imageH = (wxUint16)rdp.tbuff_tex->height; + d.frameY = (wxUint16)ul_y; + d.frameH = (wxUint16)(rdp.tbuff_tex->height); + FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.tbuff_tex->width, rdp.tbuff_tex->height); + d.scaleX = 1.0f; + d.scaleY = 1.0f; + DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width); + rdp.tbuff_tex->drawn = TRUE; + } + return; + } + //*/ + // framebuffer workaround for Zelda: MM LOT + if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000) + return; + + /*Gonetz*/ + //hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene + if ((settings.hacks&hack_Zelda) && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end) + { + FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.cur_cache[0]->addr, rdp.cimg, rdp.cimg+rdp.ci_width*rdp.ci_height*2); + rdp.tri_n += 2; + return; + } + //* + //hack for Banjo2. it removes black texrects under Banjo + if (!fb_hwfbe_enabled && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000) + { + rdp.tri_n += 2; + return; + } + //*/ + //* + //remove motion blur in night vision + if ((settings.ucode == ucode_PerfectDark) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) + { + if (fb_emulation_enabled) + if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self) + { + //FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1], rdp.maincimg[1]+rdp.ci_width*rdp.ci_height*rdp.ci_size); + LRDP("Wrong Texrect.\n"); + rdp.tri_n += 2; + return; + } + } + //*/ + + int i; + + wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); + + rdp.texrecting = 1; + + wxUint32 prev_tile = rdp.cur_tile; + rdp.cur_tile = tile; + + const float Z = set_sprite_combine_mode (); + + rdp.texrecting = 0; + + if (!rdp.cur_cache[0]) + { + rdp.cur_tile = prev_tile; + rdp.tri_n += 2; + return; + } + // **** + // ** Texrect offset by Gugaman ** + // + //integer representation of texture coordinate. + //needed to detect and avoid overflow after shifting + wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF; + wxInt32 off_y_i = rdp.cmd2 & 0xFFFF; + float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; + float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; + if (off_x_i & 0x8000) //check for sign bit + off_x_i |= ~0xffff; //make it negative + //the same as for off_x_i + if (off_y_i & 0x8000) + off_y_i |= ~0xffff; + + if (rdp.cycle_mode == 2) + dsdx /= 4.0f; + + float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x; + float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x; + float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y; + float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y; + + FRDP("texrect (%.2f, %.2f, %.2f, %.2f), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); + FRDP ("(%f, %f) -> (%f, %f), s: (%d, %d) -> (%d, %d)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y, rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); + FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x_i/32.0f, off_y_i/32.0f, dsdx, dtdy); + + float off_size_x; + float off_size_y; + + if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip + { +#ifdef TEXTURE_FILTER + if (rdp.cur_cache[0]->is_hires_tex) + { + off_size_x = (float)((lr_y - ul_y) * dsdx); + off_size_y = (float)((lr_x - ul_x) * dtdy); + } + else +#endif + { + off_size_x = (lr_y - ul_y - 1) * dsdx; + off_size_y = (lr_x - ul_x - 1) * dtdy; + } + } + else + { +#ifdef TEXTURE_FILTER + if (rdp.cur_cache[0]->is_hires_tex) + { + off_size_x = (float)((lr_x - ul_x) * dsdx); + off_size_y = (float)((lr_y - ul_y) * dtdy); + } + else +#endif + { + off_size_x = (lr_x - ul_x - 1) * dsdx; + off_size_y = (lr_y - ul_y - 1) * dtdy; + } + } + + struct { + float ul_u, ul_v, lr_u, lr_v; + } texUV[2]; //struct for texture coordinates + //angrylion's macro, helps to cut overflowed values. + #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff)) + + //calculate texture coordinates + for (int i = 0; i < 2; i++) + { + if (rdp.cur_cache[i] && (rdp.tex & (i+1))) + { + float sx = 1, sy = 1; + int x_i = off_x_i, y_i = off_y_i; + TILE & tile = rdp.tiles[rdp.cur_tile + i]; + //shifting + if (tile.shift_s) + { + if (tile.shift_s > 10) + { + wxUint8 iShift = (16 - tile.shift_s); + x_i <<= iShift; + sx = (float)(1 << iShift); + } + else + { + wxUint8 iShift = tile.shift_s; + x_i >>= iShift; + sx = 1.0f/(float)(1 << iShift); + } + } + if (tile.shift_t) + { + if (tile.shift_t > 10) + { + wxUint8 iShift = (16 - tile.shift_t); + y_i <<= iShift; + sy = (float)(1 << iShift); + } + else + { + wxUint8 iShift = tile.shift_t; + y_i >>= iShift; + sy = 1.0f/(float)(1 << iShift); + } + } + + if (rdp.aTBuffTex[i]) //hwfbe texture + { + float t0_off_x; + float t0_off_y; + if (off_x_i + off_y_i == 0) + { + t0_off_x = tile.ul_s; + t0_off_y = tile.ul_t; + } + else + { + t0_off_x = off_x_i/32.0f; + t0_off_y = off_y_i/32.0f; + } + t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur + t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t; + texUV[i].ul_u = t0_off_x * sx; + texUV[i].ul_v = t0_off_y * sy; + + texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; + texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; + + texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale; + texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale; + texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale; + texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale; + FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n", + i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v); + } + else //common case + { + //kill 10.5 format overflow by SIGN16 macro + texUV[i].ul_u = SIGN16(x_i) / 32.0f; + texUV[i].ul_v = SIGN16(y_i) / 32.0f; + + texUV[i].ul_u -= tile.f_ul_s; + texUV[i].ul_v -= tile.f_ul_t; + + texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; + texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; + + texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u; + texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u; + texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v; + texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v; + } + } + else + { + texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0; + } + } + rdp.cur_tile = prev_tile; + + // **** + + FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); + + CCLIP2 (s_ul_x, s_lr_x, texUV[0].ul_u, texUV[0].lr_u, texUV[1].ul_u, texUV[1].lr_u, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); + CCLIP2 (s_ul_y, s_lr_y, texUV[0].ul_v, texUV[0].lr_v, texUV[1].ul_v, texUV[1].lr_v, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); + + FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); + + VERTEX vstd[4] = { + { s_ul_x, s_ul_y, Z, 1.0f, texUV[0].ul_u, texUV[0].ul_v, texUV[1].ul_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, + { s_lr_x, s_ul_y, Z, 1.0f, texUV[0].lr_u, texUV[0].ul_v, texUV[1].lr_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, + { s_ul_x, s_lr_y, Z, 1.0f, texUV[0].ul_u, texUV[0].lr_v, texUV[1].ul_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 }, + { s_lr_x, s_lr_y, Z, 1.0f, texUV[0].lr_u, texUV[0].lr_v, texUV[1].lr_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 } }; + + if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip + { + vstd[1].u0 = texUV[0].ul_u; + vstd[1].v0 = texUV[0].lr_v; + vstd[1].u1 = texUV[1].ul_u; + vstd[1].v1 = texUV[1].lr_v; + + vstd[2].u0 = texUV[0].lr_u; + vstd[2].v0 = texUV[0].ul_v; + vstd[2].u1 = texUV[1].lr_u; + vstd[2].v1 = texUV[1].ul_v; + } + + VERTEX *vptr = vstd; + int n_vertices = 4; + + VERTEX *vnew = 0; + // for (int j =0; j < 4; j++) + // FRDP("v[%d] u0: %f, v0: %f, u1: %f, v1: %f\n", j, vstd[j].u0, vstd[j].v0, vstd[j].u1, vstd[j].v1); + + + if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1) + { + // ** LARGE TEXTURE HANDLING ** + // *VERY* simple algebra for texrects + float min_u, min_x, max_u, max_x; + if (vstd[0].u0 < vstd[1].u0) + { + min_u = vstd[0].u0; + min_x = vstd[0].x; + max_u = vstd[1].u0; + max_x = vstd[1].x; + } + else + { + min_u = vstd[1].u0; + min_x = vstd[1].x; + max_u = vstd[0].u0; + max_x = vstd[0].x; + } + + int start_u_256, end_u_256; + start_u_256 = (int)min_u >> 8; + end_u_256 = (int)max_u >> 8; + //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256); + + int splitheight = rdp.cur_cache[0]->splitheight; + + int num_verts_line = 2 + ((end_u_256-start_u_256)<<1); + n_vertices = num_verts_line << 1; + vnew = new VERTEX [n_vertices]; + vptr = vnew; + + vnew[0] = vstd[0]; + vnew[0].u0 -= 256.0f * start_u_256; + vnew[0].v0 += splitheight * start_u_256; + vnew[0].u1 -= 256.0f * start_u_256; + vnew[0].v1 += splitheight * start_u_256; + vnew[1] = vstd[2]; + vnew[1].u0 -= 256.0f * start_u_256; + vnew[1].v0 += splitheight * start_u_256; + vnew[1].u1 -= 256.0f * start_u_256; + vnew[1].v1 += splitheight * start_u_256; + vnew[n_vertices-2] = vstd[1]; + vnew[n_vertices-2].u0 -= 256.0f * end_u_256; + vnew[n_vertices-2].v0 += splitheight * end_u_256; + vnew[n_vertices-2].u1 -= 256.0f * end_u_256; + vnew[n_vertices-2].v1 += splitheight * end_u_256; + vnew[n_vertices-1] = vstd[3]; + vnew[n_vertices-1].u0 -= 256.0f * end_u_256; + vnew[n_vertices-1].v0 += splitheight * end_u_256; + vnew[n_vertices-1].u1 -= 256.0f * end_u_256; + vnew[n_vertices-1].v1 += splitheight * end_u_256; + + // find the equation of the line of u,x + float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u + float b = min_x - m * min_u; // b = y - m * x + + for (i=start_u_256; i 12) + { + float texbound = (float)(splitheight << 1); + for (int k = 0; k < n_vertices; k ++) + { + if (vnew[k].v0 > texbound) + vnew[k].v0 = (float)fmod(vnew[k].v0, texbound); + } + } + //*/ + } + + AllowShadeMods (vptr, n_vertices); + for (i=0; i= RDP::fog_blend) + { + float fog; + if (rdp.fog_mode == RDP::fog_blend) + fog = 1.0f/max(1, rdp.fog_color&0xFF); + else + fog = 1.0f/max(1, (~rdp.fog_color)&0xFF); + for (i = 0; i < n_vertices; i++) + { + vptr[i].f = fog; + } + grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); + } + + ConvertCoordsConvert (vptr, n_vertices); + + if (settings.wireframe) + { + SetWireframeCol (); + grDrawLine (&vstd[0], &vstd[2]); + grDrawLine (&vstd[2], &vstd[1]); + grDrawLine (&vstd[1], &vstd[0]); + grDrawLine (&vstd[2], &vstd[3]); + grDrawLine (&vstd[3], &vstd[1]); + } + else + { + grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX)); + } + + if (_debugger.capture) + { + VERTEX vl[3]; + vl[0] = vstd[0]; + vl[1] = vstd[2]; + vl[2] = vstd[1]; + add_tri (vl, 3, TRI_TEXRECT); + rdp.tri_n ++; + vl[0] = vstd[2]; + vl[1] = vstd[3]; + vl[2] = vstd[1]; + add_tri (vl, 3, TRI_TEXRECT); + rdp.tri_n ++; + } + else + rdp.tri_n += 2; + } + else + { + rdp.tri_n += 2; + } + + delete[] vnew; +} + +static void rdp_loadsync() +{ + LRDP("loadsync - ignored\n"); +} + +static void rdp_pipesync() +{ + LRDP("pipesync - ignored\n"); +} + +static void rdp_tilesync() +{ + LRDP("tilesync - ignored\n"); +} + +static void rdp_fullsync() +{ + // Set an interrupt to allow the game to continue + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + LRDP("fullsync\n"); +} + +static void rdp_setkeygb() +{ + wxUint32 sB = rdp.cmd1&0xFF; + wxUint32 cB = (rdp.cmd1>>8)&0xFF; + wxUint32 sG = (rdp.cmd1>>16)&0xFF; + wxUint32 cG = (rdp.cmd1>>24)&0xFF; + rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8); + rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8); + FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB); +} + +static void rdp_setkeyr() +{ + wxUint32 sR = rdp.cmd1&0xFF; + wxUint32 cR = (rdp.cmd1>>8)&0xFF; + rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24); + rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24); + FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR); +} + +static void rdp_setconvert() +{ + /* + rdp.YUV_C0 = 1.1647f ; + rdp.YUV_C1 = 0.79931f ; + rdp.YUV_C2 = -0.1964f ; + rdp.YUV_C3 = -0.40651f; + rdp.YUV_C4 = 1.014f ; + */ + rdp.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF; + rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF); + // RDP_E("setconvert - IGNORED\n"); + FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5); +} + +// +// setscissor - sets the screen clipping rectangle +// + +static void rdp_setscissor() +{ + // clipper resolution is 320x240, scale based on computer resolution + rdp.scissor_o.ul_x = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; + rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; + rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; + rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; + + rdp.ci_upper_bound = rdp.scissor_o.ul_y; + rdp.ci_lower_bound = rdp.scissor_o.lr_y; + rdp.scissor_set = TRUE; + + FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y, + rdp.scissor_o.lr_x, rdp.scissor_o.lr_y); + + rdp.update |= UPDATE_SCISSOR; + + if (rdp.view_scale[0] == 0) //viewport is not set? + { + rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x; + rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y; + rdp.view_trans[0] = rdp.view_scale[0]; + rdp.view_trans[1] = -rdp.view_scale[1]; + rdp.update |= UPDATE_VIEWPORT; + } +} + +static void rdp_setprimdepth() +{ + rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF); + rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF); + + FRDP("setprimdepth: %d\n", rdp.prim_depth); +} + +static void rdp_setothermode() +{ +#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \ + rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \ + rdp.cmd1 = data; \ + gfx_instruction[settings.ucode][cmd] (); \ +} +#define SETOTHERMODE(cmd,sft,len,data) { \ + rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \ + rdp.cmd1 = data; \ + gfx_instruction[settings.ucode][cmd] (); \ +} + + LRDP("rdp_setothermode\n"); + + if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD)) + { + int cmd0 = rdp.cmd0; + F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L + F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H + } + else + { + int cmd0 = rdp.cmd0; + SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L + SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H + } +} + +void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count) +{ + LRDP("Loading palette... "); + wxUint16 *dpal = rdp.pal_8 + start; + wxUint16 end = start+count; +#ifdef TEXTURE_FILTER + wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK)); +#endif + + for (wxUint16 i=start; i>= 4; + end = start + (count >> 4); + if (end == start) // it can be if count < 16 + end = start + 1; + for (wxUint16 p = start; p < end; p++) + { + rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); + } + rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); + LRDP("Done.\n"); +} + +static void rdp_loadtlut() +{ + wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; + wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes + // wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1; + wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy + + if (rdp.timg.addr + (count<<1) > BMASK) + count = (wxUint16)((BMASK - rdp.timg.addr) >> 1); + + if (start+count > 256) count = 256-start; + + FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count, + rdp.timg.addr); + + load_palette (rdp.timg.addr, start, count); + + rdp.timg.addr += count << 1; + + if (rdp.tbuff_tex) //paranoid check. + { + //the buffer is definitely wrong, as there must be no CI frame buffers + //find and remove it + for (int i = 0; i < voodoo.num_tmu; i++) + { + for (int j = 0; j < rdp.texbufs[i].count; j++) + { + if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex) + { + rdp.texbufs[i].count--; + if (j < rdp.texbufs[i].count) + memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j)); + return; + } + } + } + } +} + +int tile_set = 0; +static void rdp_settilesize() +{ + wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; + rdp.last_tile_size = tile; + + rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f; + rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f; + + int ul_s = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff); + int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff); + int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff); + int lr_t = (((wxUint16)(rdp.cmd1 >> 2 )) & 0x03ff); + + if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size + wrong_tile = tile; + else if (wrong_tile == (int)tile) + wrong_tile = -1; + + if (settings.use_sts1_only) + { + // ** USE FIRST SETTILESIZE ONLY ** + // This option helps certain textures while using the 'Alternate texture size method', + // but may break others. (should help more than break) + + if (tile_set) + { + // coords in 10.2 format + rdp.tiles[tile].ul_s = ul_s; + rdp.tiles[tile].ul_t = ul_t; + rdp.tiles[tile].lr_s = lr_s; + rdp.tiles[tile].lr_t = lr_t; + tile_set = 0; + } + } + else + { + // coords in 10.2 format + rdp.tiles[tile].ul_s = ul_s; + rdp.tiles[tile].ul_t = ul_t; + rdp.tiles[tile].lr_s = lr_s; + rdp.tiles[tile].lr_t = lr_t; + } + + // handle wrapping + if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400; + if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400; + + rdp.update |= UPDATE_TEXTURE; + + rdp.first = 1; + + FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n", + tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t); +} + +void setTBufTex(wxUint16 t_mem, wxUint32 cnt) +{ + FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt); + TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex; + for (int i = 0; i < 2; i++) + { + LRDP("Before: "); + if (rdp.aTBuffTex[i]) { + FRDP("rdp.aTBuffTex[%d]: tmu=%d t_mem=%d tile=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem, rdp.aTBuffTex[i]->tile); + } else { + FRDP("rdp.aTBuffTex[%d]=0\n", i); + } + if ((rdp.aTBuffTex[i] == 0 && rdp.aTBuffTex[i^1] != pTbufTex) || (rdp.aTBuffTex[i] && rdp.aTBuffTex[i]->t_mem >= t_mem && rdp.aTBuffTex[i]->t_mem < t_mem + cnt)) + { + if (pTbufTex) + { + rdp.aTBuffTex[i] = pTbufTex; + rdp.aTBuffTex[i]->t_mem = t_mem; + pTbufTex = 0; + FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem); + } + else + { + rdp.aTBuffTex[i] = 0; + FRDP("rdp.aTBuffTex[%d]=0\n", i); + } + } + } +} + +static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt) +{ + uint32_t *v5; + int v6; + uint32_t *v7; + uint32_t v8; + int v9; + uint32_t v10; + uint32_t *v11; + uint32_t v12; + uint32_t v13; + uint32_t v14; + int v15; + int v16; + uint32_t *v17; + int v18; + uint32_t v19; + uint32_t v20; + int i; + + v5 = dst; + v6 = cnt; + if ( cnt ) + { + v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC)); + v8 = off & 3; + if ( !(off & 3) ) + goto LABEL_23; + v9 = 4 - v8; + v10 = *v7; + v11 = v7 + 1; + do + { + v10 = __ROL__(v10, 8); + --v8; + } + while ( v8 ); + do + { + v10 = __ROL__(v10, 8); + *(uint8_t *)v5 = v10; + v5 = (uint32_t *)((char *)v5 + 1); + --v9; + } + while ( v9 ); + v12 = *v11; + v7 = v11 + 1; + *v5 = bswap32(v12); + ++v5; + v6 = cnt - 1; + if ( cnt != 1 ) + { +LABEL_23: + do + { + *v5 = bswap32(*v7); + v5[1] = bswap32(v7[1]); + v7 += 2; + v5 += 2; + --v6; + } + while ( v6 ); + } + v13 = off & 3; + if ( off & 3 ) + { + v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC)); + do + { + v14 = __ROL__(v14, 8); + *(uint8_t *)v5 = v14; + v5 = (uint32_t *)((char *)v5 + 1); + --v13; + } + while ( v13 ); + } + } + v15 = cnt; + v16 = 0; + v17 = dst; + v18 = 0; +dxt_test: + while ( 1 ) + { + v17 += 2; + --v15; + if ( !v15 ) + break; + v16 += dxt; + if ( v16 < 0 ) + { + while ( 1 ) + { + ++v18; + --v15; + if ( !v15 ) + goto end_dxt_test; + v16 += dxt; + if ( v16 >= 0 ) + { + for ( i = v15; v18; --v18 ) + { + v19 = *v17; + *v17 = v17[1]; + v17[1] = v19; + v17 += 2; + } + v15 = i; + goto dxt_test; + } + } + } + } +end_dxt_test: + while ( v18 ) + { + v20 = *v17; + *v17 = v17[1]; + v17[1] = v20; + v17 += 2; + --v18; + } +} + +void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt); +static void rdp_loadblock() +{ + if (rdp.skip_drawing) + { + LRDP("loadblock skipped\n"); + return; + } + wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); + wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF); + wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF; + if (ucode5_texshiftaddr) + { + if (ucode5_texshift % ((lr_s+1)<<3)) + { + rdp.timg.addr -= ucode5_texshift; + ucode5_texshiftaddr = 0; + ucode5_texshift = 0; + ucode5_texshiftcount = 0; + } + else + ucode5_texshiftcount++; + } + + rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; + + // ** DXT is used for swapping every other line + /* double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error + wxUint32 _dxt = (wxUint32)fdxt;*/ + + // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) + wxUint32 _dxt = dxt << 20; + + wxUint32 addr = segoffset(rdp.timg.addr) & BMASK; + + // lr_s specifies number of 64-bit words to copy + // 10.2 format + wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF; + wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF; + + rdp.tiles[tile].ul_s = ul_s; + rdp.tiles[tile].ul_t = ul_t; + rdp.tiles[tile].lr_s = lr_s; + + rdp.timg.set_by = 0; // load block + +#ifdef TEXTURE_FILTER + LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; + info.tile_width = lr_s; + info.dxt = dxt; +#endif + + // do a quick boundary check before copying to eliminate the possibility for exception + if (ul_s >= 512) { + lr_s = 1; // 1 so that it doesn't die on memcpy + ul_s = 511; + } + if (ul_s+lr_s > 512) + lr_s = 512-ul_s; + + if (addr+(lr_s<<3) > BMASK+1) + lr_s = (wxUint16)((BMASK-addr)>>3); + + //angrylion's advice to use ul_s in texture image offset and cnt calculations. + //Helps to fix Vigilante 8 jpeg backgrounds and logos + wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1); + unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); + wxUint32 cnt = lr_s-ul_s+1; + if (rdp.tiles[tile].size == 3) + cnt <<= 1; + + if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) { + WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem)); + cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem); + } + + if (rdp.timg.size == 3) + LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt); + else + loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt); + + rdp.timg.addr += cnt << 3; + rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11); + + rdp.update |= UPDATE_TEXTURE; + + FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n", + tile, ul_s, ul_t, lr_s, + dxt, _dxt); + + if (fb_hwfbe_enabled) + setTBufTex(rdp.tiles[tile].t_mem, cnt); +} + + +static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end) +{ + uint32_t *v7; + int v8; + uint32_t *v9; + int v10; + int v11; + int v12; + uint32_t *v13; + int v14; + int v15; + uint32_t v16; + uint32_t *v17; + uint32_t v18; + int v19; + uint32_t v20; + int v21; + uint32_t v22; + int v23; + uint32_t *v24; + int v25; + int v26; + uint32_t *v27; + int v28; + int v29; + int v30; + uint32_t *v31; + + v7 = dst; + v8 = width; + v9 = src; + v10 = off; + v11 = 0; + v12 = height; + do + { + if ( end < v7 ) + break; + v31 = v7; + v30 = v8; + v29 = v12; + v28 = v11; + v27 = v9; + v26 = v10; + if ( v8 ) + { + v25 = v8; + v24 = v9; + v23 = v10; + v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC)); + v14 = v10 & 3; + if ( !(v10 & 3) ) + goto LABEL_20; + v15 = 4 - v14; + v16 = *v13; + v17 = v13 + 1; + do + { + v16 = __ROL__(v16, 8); + --v14; + } + while ( v14 ); + do + { + v16 = __ROL__(v16, 8); + *(uint8_t *)v7 = v16; + v7 = (uint32_t *)((char *)v7 + 1); + --v15; + } + while ( v15 ); + v18 = *v17; + v13 = v17 + 1; + *v7 = bswap32(v18); + ++v7; + --v8; + if ( v8 ) + { +LABEL_20: + do + { + *v7 = bswap32(*v13); + v7[1] = bswap32(v13[1]); + v13 += 2; + v7 += 2; + --v8; + } + while ( v8 ); + } + v19 = v23 & 3; + if ( v23 & 3 ) + { + v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC)); + do + { + v20 = __ROL__(v20, 8); + *(uint8_t *)v7 = v20; + v7 = (uint32_t *)((char *)v7 + 1); + --v19; + } + while ( v19 ); + } + } + v9 = v27; + v21 = v29; + v8 = v30; + v11 = v28 ^ 1; + if ( v28 == 1 ) + { + v7 = v31; + if ( v30 ) + { + do + { + v22 = *v7; + *v7 = v7[1]; + v7[1] = v22; + v7 += 2; + --v8; + } + while ( v8 ); + } + v21 = v29; + v8 = v30; + } + v10 = line + v26; + v12 = v21 - 1; + } + while ( v12 ); +} + +void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height); +static void rdp_loadtile() +{ + if (rdp.skip_drawing) + { + LRDP("loadtile skipped\n"); + return; + } + rdp.timg.set_by = 1; // load tile + + wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); + + rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; + + wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF); + wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF); + wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF); + wxUint16 lr_t = (wxUint16)((rdp.cmd1 >> 2 ) & 0x03FF); + + if (lr_s < ul_s || lr_t < ul_t) return; + + if (wrong_tile >= 0) //there was a tile with zero length + { + rdp.tiles[wrong_tile].lr_s = lr_s; + + if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size) + rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size); + else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size) + rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size); + rdp.tiles[wrong_tile].lr_t = lr_t; + rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0; + // wrong_tile = -1; + } + + if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0)) + { + FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); + rdp.tbuff_tex->tile_uls = ul_s; + rdp.tbuff_tex->tile_ult = ul_t; + } + + if ((settings.hacks&hack_Tonic) && tile == 7) + { + rdp.tiles[0].ul_s = ul_s; + rdp.tiles[0].ul_t = ul_t; + rdp.tiles[0].lr_s = lr_s; + rdp.tiles[0].lr_t = lr_t; + } + + wxUint32 height = lr_t - ul_t + 1; // get height + wxUint32 width = lr_s - ul_s + 1; + +#ifdef TEXTURE_FILTER + LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; + info.tile_ul_s = ul_s; + info.tile_ul_t = ul_t; + info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<> 1; + wxUint32 offs = ul_t * line_n; + offs += ul_s << rdp.tiles[tile].size >> 1; + offs += rdp.timg.addr; + if (offs >= BMASK) + return; + + if (rdp.timg.size == 3) + { + LoadTile32b(tile, ul_s, ul_t, width, height); + } + else + { + // check if points to bad location + if (offs + line_n*height > BMASK) + height = (BMASK - offs) / line_n; + if (height == 0) + return; + + wxUint32 wid_64 = rdp.tiles[tile].line; + unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); + unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3); + loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end); + } + FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile, + ul_s, ul_t, lr_s, lr_t); + + if (fb_hwfbe_enabled) + setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height); +} + +static void rdp_settile() +{ + tile_set = 1; // used to check if we only load the first settilesize + + rdp.first = 0; + + rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); + TILE *tile = &rdp.tiles[rdp.last_tile]; + + tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); + tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); + tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF); + tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF); + tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F); + tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01); + tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01); + tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F); + tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F); + tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01); + tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01); + tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F); + tile->shift_s = (wxUint8)(rdp.cmd1 & 0x0F); + + rdp.update |= UPDATE_TEXTURE; + + FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, " + "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, " + "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n", + rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line, + tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t, + tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s); + + if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2) + { + for (int i = 0; i < 2; i++) + { + if (rdp.aTBuffTex[i]) + { + if (rdp.aTBuffTex[i]->t_mem == tile->t_mem) + { + if (rdp.aTBuffTex[i]->size == tile->size) + { + rdp.aTBuffTex[i]->tile = rdp.last_tile; + rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88; + FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88"); + } + else + rdp.aTBuffTex[i] = 0; + break; + } + else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same + rdp.aTBuffTex[i] = 0; + } + } + } +} + +// +// fillrect - fills a rectangle +// + +static void rdp_fillrect() +{ + wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); + wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; + wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; + wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; + if ((ul_x > lr_x) || (ul_y > lr_y)) + { + LRDP("Fillrect. Wrong coordinates. Skipped\n"); + return; + } + int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC); + if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer) + { + LRDP("Fillrect - cleared the depth buffer\n"); + if (fullscreen) + { + if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers + { + update_scissor (); + grDepthMask (FXTRUE); + grColorMask (FXFALSE, FXFALSE); + grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF); + grColorMask (FXTRUE, FXTRUE); + rdp.update |= UPDATE_ZBUF_ENABLED; + } + //if (settings.frame_buffer&fb_depth_clear) + { + ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); + lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); + ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); + lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); + wxUint32 zi_width_in_dwords = rdp.ci_width >> 1; + ul_x >>= 1; + lr_x >>= 1; + wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg); + dst += ul_y * zi_width_in_dwords; + for (wxUint32 y = ul_y; y < lr_y; y++) + { + for (wxUint32 x = ul_x; x < lr_x; x++) + { + dst[x] = rdp.fill_color; + } + dst += zi_width_in_dwords; + } + } + } + return; + } + + if (rdp.skip_drawing) + { + LRDP("Fillrect skipped\n"); + return; + } + + if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x - ul_x) && (rdp.cur_image->height == lr_y - ul_y)) + { + wxUint32 color = rdp.fill_color; + if (rdp.ci_size < 3) + { + color = ((color&1)?0xFF:0) | + ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | + ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | + ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); + } + grDepthMask (FXFALSE); + grBufferClear (color, 0, 0xFFFF); + grDepthMask (FXTRUE); + rdp.update |= UPDATE_ZBUF_ENABLED; + LRDP("Fillrect - cleared the texture buffer\n"); + return; + } + + // Update scissor + if (fullscreen) + update_scissor (); + + if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0) + { + lr_x--; lr_y--; + } + FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode, + rdp.tri_n, rdp.tri_n+1); + + FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, + rdp.scissor.lr_y); + + // KILL the floating point error with 0.01f + wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); + wxInt32 s_lr_y = (wxUint32)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); + + if (s_lr_x < 0) s_lr_x = 0; + if (s_lr_y < 0) s_lr_y = 0; + if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x; + if ((wxUint32)s_ul_y > settings.res_y) s_ul_y = settings.res_y; + + FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); + + if (fullscreen) + { + grFogMode (GR_FOG_DISABLE); + + const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode(); + + // Draw the rectangle + VERTEX v[4] = { + { (float)s_ul_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, + { (float)s_lr_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, + { (float)s_ul_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0}, + { (float)s_lr_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, {0,0,0,0}, 0,0, 0,0,0,0} }; + + if (rdp.cycle_mode == 3) + { + wxUint32 color = rdp.fill_color; + + if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) + { + //background of auxiliary frame buffers must have zero alpha. + //make it black, set 0 alpha to plack pixels on frame buffer read + color = 0; + } + else if (rdp.ci_size < 3) + { + color = ((color&1)?0xFF:0) | + ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | + ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | + ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); + } + + grConstantColorValue (color); + + grColorCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); + + grAlphaTestFunction (GR_CMP_ALWAYS); + if (grStippleModeExt) + grStippleModeExt(GR_STIPPLE_DISABLE); + + grCullMode(GR_CULL_DISABLE); + grFogMode (GR_FOG_DISABLE); + grDepthBufferFunction (GR_CMP_ALWAYS); + grDepthMask (FXFALSE); + + rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED; + } + else + { + wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); + wxUint32 cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); + if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade + { + AllowShadeMods (v, 4); + for (int k = 0; k < 4; k++) + apply_shade_mods (&v[k]); + } + if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64 + { + grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF)); + rdp.update |= UPDATE_COMBINE; + } + } + + if (settings.wireframe) + { + SetWireframeCol (); + grDrawLine (&v[0], &v[2]); + grDrawLine (&v[2], &v[1]); + grDrawLine (&v[1], &v[0]); + grDrawLine (&v[2], &v[3]); + grDrawLine (&v[3], &v[1]); + //grDrawLine (&v[1], &v[2]); + } + else + { + grDrawTriangle (&v[0], &v[2], &v[1]); + grDrawTriangle (&v[2], &v[3], &v[1]); + } + + if (_debugger.capture) + { + VERTEX v1[3]; + v1[0] = v[0]; + v1[1] = v[2]; + v1[2] = v[1]; + add_tri (v1, 3, TRI_FILLRECT); + rdp.tri_n ++; + v1[0] = v[2]; + v1[1] = v[3]; + add_tri (v1, 3, TRI_FILLRECT); + rdp.tri_n ++; + } + else + rdp.tri_n += 2; + } + else + { + rdp.tri_n += 2; + } +} + +// +// setfillcolor - sets the filling color +// + +static void rdp_setfillcolor() +{ + rdp.fill_color = rdp.cmd1; + rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; + + FRDP("setfillcolor: %08lx\n", rdp.cmd1); +} + +static void rdp_setfogcolor() +{ + rdp.fog_color = rdp.cmd1; + rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED; + + FRDP("setfogcolor - %08lx\n", rdp.cmd1); +} + +static void rdp_setblendcolor() +{ + rdp.blend_color = rdp.cmd1; + rdp.update |= UPDATE_COMBINE; + + FRDP("setblendcolor: %08lx\n", rdp.cmd1); +} + +static void rdp_setprimcolor() +{ + rdp.prim_color = rdp.cmd1; + rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF; + rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin); + rdp.update |= UPDATE_COMBINE; + + FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin, + rdp.prim_lodfrac); +} + +static void rdp_setenvcolor() +{ + rdp.env_color = rdp.cmd1; + rdp.update |= UPDATE_COMBINE; + + FRDP("setenvcolor: %08lx\n", rdp.cmd1); +} + +static void rdp_setcombine() +{ + rdp.c_a0 = (wxUint8)((rdp.cmd0 >> 20) & 0xF); + rdp.c_b0 = (wxUint8)((rdp.cmd1 >> 28) & 0xF); + rdp.c_c0 = (wxUint8)((rdp.cmd0 >> 15) & 0x1F); + rdp.c_d0 = (wxUint8)((rdp.cmd1 >> 15) & 0x7); + rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7); + rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7); + rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9) & 0x7); + rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9) & 0x7); + + rdp.c_a1 = (wxUint8)((rdp.cmd0 >> 5) & 0xF); + rdp.c_b1 = (wxUint8)((rdp.cmd1 >> 24) & 0xF); + rdp.c_c1 = (wxUint8)((rdp.cmd0 >> 0) & 0x1F); + rdp.c_d1 = (wxUint8)((rdp.cmd1 >> 6) & 0x7); + rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7); + rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3) & 0x7); + rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7); + rdp.c_Ad1 = (wxUint8)((rdp.cmd1 >> 0) & 0x7); + + rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)| + (rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25); + rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)| + (rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25); + + rdp.update |= UPDATE_COMBINE; + + FRDP("setcombine\na0=%s b0=%s c0=%s d0=%s\nAa0=%s Ab0=%s Ac0=%s Ad0=%s\na1=%s b1=%s c1=%s d1=%s\nAa1=%s Ab1=%s Ac1=%s Ad1=%s\n", + Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0], + Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0], + Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1], + Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]); +} + +// +// settextureimage - sets the source for an image copy +// + +static void rdp_settextureimage() +{ + static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; + static const char *size[] = { "4bit", "8bit", "16bit", "32bit" }; + + rdp.timg.format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); + rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); + rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF)); + rdp.timg.addr = segoffset(rdp.cmd1); + if (ucode5_texshiftaddr) + { + if (rdp.timg.format == 0) + { + wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr); + ucode5_texshift = t[ucode5_texshiftcount^1]; + rdp.timg.addr += ucode5_texshift; + } + else + { + ucode5_texshiftaddr = 0; + ucode5_texshift = 0; + ucode5_texshiftcount = 0; + } + } + rdp.s2dex_tex_loaded = TRUE; + rdp.update |= UPDATE_TEXTURE; + + if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end)) + { + if (!rdp.fb_drawn) + { + if (!rdp.cur_image) + CopyFrameBuffer(); + else + CloseTextureBuffer(TRUE); + rdp.fb_drawn = TRUE; + } + } + + if (fb_hwfbe_enabled) //search this texture among drawn texture buffers + FindTextureBuffer(rdp.timg.addr, rdp.timg.width); + + FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n", + format[rdp.timg.format], size[rdp.timg.size], + rdp.timg.width, rdp.timg.addr); +} + +static void rdp_setdepthimage() +{ + rdp.zimg = segoffset(rdp.cmd1) & BMASK; + rdp.zi_width = rdp.ci_width; + FRDP("setdepthimage - %08lx\n", rdp.zimg); +} + +int SwapOK = TRUE; +static void RestoreScale() +{ + FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak); + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + // update_scissor(); + rdp.view_scale[0] *= rdp.scale_x; + rdp.view_scale[1] *= rdp.scale_y; + rdp.view_trans[0] *= rdp.scale_x; + rdp.view_trans[1] *= rdp.scale_y; + rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; + //* + if (fullscreen) + { + grDepthMask (FXFALSE); + grBufferClear (0, 0, 0xFFFF); + grDepthMask (FXTRUE); + } + //*/ +} + +static wxUint32 swapped_addr = 0; + +static void rdp_setcolorimage() +{ + if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF)) + { + COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count]; + COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count?rdp.ci_count-1:0]; + COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; + switch (cur_fb.status) + { + case ci_main: + { + + if (rdp.ci_count == 0) + { + if ((rdp.ci_status == ci_aux)) //for PPL + { + float sx = rdp.scale_x; + float sy = rdp.scale_y; + rdp.scale_x = 1.0f; + rdp.scale_y = 1.0f; + CopyFrameBuffer (); + rdp.scale_x = sx; + rdp.scale_y = sy; + } + if (!fb_hwfbe_enabled) + { + if ((rdp.num_of_ci > 1) && + (next_fb.status == ci_aux) && + (next_fb.width >= cur_fb.width)) + { + rdp.scale_x = 1.0f; + rdp.scale_y = 1.0f; + } + } + else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index)) + { + if (next_fb.status == ci_aux_copy) + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + else + OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]); + } + else if (fb_hwfbe_enabled && prev_fb.status == ci_aux) + { + if (rdp.motionblur) + { + rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]); + grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); + grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2, + rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH ); + } + else if (rdp.read_whole_frame) + { + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + } + //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index) + // CloseTextureBuffer(); + + rdp.skip_drawing = FALSE; + } + break; + case ci_copy: + { + if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) + { + if (cur_fb.width == rdp.ci_width) + { + if (CopyTextureBuffer(prev_fb, cur_fb)) + { + // if (CloseTextureBuffer(TRUE)) + //* + if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM + { + CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); + rdp.fb_drawn = TRUE; + memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<>1); + } + //*/ + } + else + { + if (!rdp.fb_drawn || prev_fb.status == ci_copy_self) + { + CopyFrameBuffer (); + rdp.fb_drawn = TRUE; + } + memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<>1); + } + } + else + { + CloseTextureBuffer(TRUE); + } + } + else + { + memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size); + } + rdp.skip_drawing = TRUE; + } + break; + case ci_aux_copy: + { + rdp.skip_drawing = FALSE; + if (CloseTextureBuffer(prev_fb.status != ci_aux_copy)) + ; + else if (!rdp.fb_drawn) + { + CopyFrameBuffer (); + rdp.fb_drawn = TRUE; + } + if (fb_hwfbe_enabled) + OpenTextureBuffer(cur_fb); + } + break; + case ci_old_copy: + { + if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) + { + if (cur_fb.width == rdp.ci_width) + { + memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<>1); + } + //rdp.skip_drawing = TRUE; + } + else + { + memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<>1); + } + } + break; + /* + else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i) + { + // CopyFrameBuffer (); + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + rdp.skip_drawing = FALSE; + } + */ + case ci_aux: + { + if (!fb_hwfbe_enabled && cur_fb.format != 0) + rdp.skip_drawing = TRUE; + else + { + rdp.skip_drawing = FALSE; + if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb)) + ; + else + { + if (cur_fb.format != 0) + rdp.skip_drawing = TRUE; + if (rdp.ci_count == 0) + { + // if (rdp.num_of_ci > 1) + // { + rdp.scale_x = 1.0f; + rdp.scale_y = 1.0f; + // } + } + else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) && + (prev_fb.width == cur_fb.width)) // for Pokemon Stadium + CopyFrameBuffer (); + } + } + cur_fb.status = ci_aux; + } + break; + case ci_zimg: + if (settings.ucode != ucode_PerfectDark) + { + if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR))) + { + GrLOD_t LOD = GR_LOD_LOG2_1024; + if (settings.scr_res_x > 1024) + LOD = GR_LOD_LOG2_2048; + grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD, + GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); + grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT ); + LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n"); + } + } + rdp.skip_drawing = TRUE; + break; + case ci_zcopy: + if (settings.ucode != ucode_PerfectDark) + { + if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count) + { + CopyDepthBuffer(); + } + rdp.skip_drawing = TRUE; + } + break; + case ci_useless: + rdp.skip_drawing = TRUE; + break; + case ci_copy_self: + if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) + OpenTextureBuffer(cur_fb); + rdp.skip_drawing = FALSE; + break; + default: + rdp.skip_drawing = FALSE; + } + + if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium + { + if (!fb_hwfbe_enabled && prev_fb.format == 0) + CopyFrameBuffer (); + else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100) + CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); + } + if (!fb_hwfbe_enabled && cur_fb.status == ci_copy) + { + if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) + { + RestoreScale(); + } + } + if (!fb_hwfbe_enabled && cur_fb.status == ci_aux) + { + if (cur_fb.format == 0) + { + if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer + { + int width = cur_fb.width; + int height = cur_fb.height; + wxUint16 *ptr_dst = new wxUint16[width*height]; + wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr); + wxUint16 c; + + for (int y=0; y> 1) | 0x8000; + ptr_dst[x + y * width] = c; + } + } + grLfbWriteRegion(GR_BUFFER_BACKBUFFER, + (wxUint32)rdp.offset_x, + (wxUint32)rdp.offset_y, + GR_LFB_SRC_FMT_555, + width, + height, + FXFALSE, + width<<1, + ptr_dst); + delete[] ptr_dst; + } + /* + else //just clear buffer + { + + grColorMask(FXTRUE, FXTRUE); + grBufferClear (0, 0, 0xFFFF); + } + */ + } + } + + if ((cur_fb.status == ci_main) && (rdp.ci_count > 0)) + { + int to_org_res = TRUE; + for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++) + { + if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy)) + { + to_org_res = FALSE; + break; + } + } + if (to_org_res) + { + LRDP("return to original scale\n"); + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + if (fb_hwfbe_enabled && !rdp.read_whole_frame) + CloseTextureBuffer(); + } + if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index)) + CloseTextureBuffer(); + + } + rdp.ci_status = cur_fb.status; + rdp.ci_count++; + } + + rdp.ocimg = rdp.cimg; + rdp.cimg = segoffset(rdp.cmd1) & BMASK; + rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1; + if (fb_emulation_enabled) + rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height; + else if (rdp.ci_width == 32) + rdp.ci_height = 32; + else + rdp.ci_height = rdp.scissor_o.lr_y; + if (rdp.zimg == rdp.cimg) + { + rdp.zi_width = rdp.ci_width; + // int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height); + // rdp.zi_words = rdp.zi_width * zi_height; + } + wxUint32 format = (rdp.cmd0 >> 21) & 0x7; + rdp.ci_size = (rdp.cmd0 >> 19) & 0x3; + rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1)); + FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size); + FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK); + + if (format != 0) //can't draw into non RGBA buffer + { + if (!rdp.cur_image) + { + if (fb_hwfbe_enabled && rdp.ci_width <= 64) + OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); + else if (format > 2) + rdp.skip_drawing = TRUE; + return; + } + } + else + { + if (!fb_emulation_enabled) + rdp.skip_drawing = FALSE; + } + + CI_SET = TRUE; + if (settings.swapmode > 0) + { + if (rdp.zimg == rdp.cimg) + rdp.updatescreen = 1; + + int viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE; + if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image) + { + if (fb_emulation_enabled) + rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; + else + rdp.maincimg[0].addr = rdp.cimg; + rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr; + swapped_addr = rdp.cimg; + newSwapBuffers(); + rdp.vi_org_reg = *gfx.VI_ORIGIN_REG; + SwapOK = FALSE; + if (fb_hwfbe_enabled) + { + if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg)) + { + int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index; + FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr); + OpenTextureBuffer(rdp.frame_buffers[idx]); + if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave + rdp.copy_ci_index = 0; + } + else if (rdp.read_whole_frame && !rdp.cur_image) + { + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + } + } + } +} + +static void rsp_reserved0() +{ + if (settings.ucode == ucode_DiddyKong) + { + ucode5_texshiftaddr = segoffset(rdp.cmd1); + ucode5_texshiftcount = 0; + FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr); + } + else + { + RDP_E("reserved0 - IGNORED\n"); + LRDP("reserved0 - IGNORED\n"); + } +} + +static void rsp_reserved1() +{ + LRDP("reserved1 - ignored\n"); +} + +static void rsp_reserved2() +{ + LRDP("reserved2\n"); +} + +static void rsp_reserved3() +{ + LRDP("reserved3 - ignored\n"); +} + +void SetWireframeCol () +{ + if (!fullscreen) return; + + switch (settings.wfmode) + { + //case 0: // normal colors, don't do anything + case 1: // vertex colors + grColorCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grAlphaBlendFunction (GR_BLEND_ONE, + GR_BLEND_ZERO, + GR_BLEND_ZERO, + GR_BLEND_ZERO); + grTexCombine (GR_TMU0, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE); + grTexCombine (GR_TMU1, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE); + break; + case 2: // red only + grColorCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grConstantColorValue (0xFF0000FF); + grAlphaBlendFunction (GR_BLEND_ONE, + GR_BLEND_ZERO, + GR_BLEND_ZERO, + GR_BLEND_ZERO); + grTexCombine (GR_TMU0, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE); + grTexCombine (GR_TMU1, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE); + break; + } + + grAlphaTestFunction (GR_CMP_ALWAYS); + grCullMode (GR_CULL_DISABLE); + + rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; +} + +/****************************************************************** +Function: FrameBufferRead +Purpose: This function is called to notify the dll that the +frame buffer memory is beening read at the given address. +DLL should copy content from its render buffer to the frame buffer +in N64 RDRAM +DLL is responsible to maintain its own frame buffer memory addr list +DLL should copy 4KB block content back to RDRAM frame buffer. +Emulator should not call this function again if other memory +is read within the same 4KB range +input: addr rdram address +val val +size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 +output: none +*******************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +EXPORT void CALL FBRead(wxUint32 addr) +{ + LOG ("FBRead ()\n"); + + if (cpu_fb_ignore) + return; + if (cpu_fb_write_called) + { + cpu_fb_ignore = TRUE; + cpu_fb_write = FALSE; + return; + } + cpu_fb_read_called = TRUE; + wxUint32 a = segoffset(addr); + FRDP("FBRead. addr: %08lx\n", a); + if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end)) + { + fbreads_back++; + //if (fbreads_back > 2) //&& (rdp.ci_width <= 320)) + { + CopyFrameBuffer (); + rdp.fb_drawn = TRUE; + } + } + if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2)) + { + fbreads_front++; + //if (fbreads_front > 2)//&& (rdp.ci_width <= 320)) + { + wxUint32 cimg = rdp.cimg; + rdp.cimg = rdp.maincimg[1].addr; + if (fb_emulation_enabled) + { + rdp.ci_width = rdp.maincimg[1].width; + rdp.ci_count = 0; + wxUint32 h = rdp.frame_buffers[0].height; + rdp.frame_buffers[0].height = rdp.maincimg[1].height; + CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); + rdp.frame_buffers[0].height = h; + } + else + { + CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); + } + rdp.cimg = cimg; + rdp.fb_drawn_front = TRUE; + } + } +} + +#if 0 +/****************************************************************** +Function: FrameBufferWriteList +Purpose: This function is called to notify the dll that the +frame buffer has been modified by CPU at the given address. +input: FrameBufferModifyEntry *plist +size = size of the plist, max = 1024 +output: none +*******************************************************************/ +EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size) +{ + LOG ("FBWList ()\n"); + FRDP("FBWList. size: %d\n", size); +} +#endif + +/****************************************************************** +Function: FrameBufferWrite +Purpose: This function is called to notify the dll that the +frame buffer has been modified by CPU at the given address. +input: addr rdram address +val val +size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 +output: none +*******************************************************************/ +EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size) +{ + LOG ("FBWrite ()\n"); + if (cpu_fb_ignore) + return; + if (cpu_fb_read_called) + { + cpu_fb_ignore = TRUE; + cpu_fb_write = FALSE; + return; + } + cpu_fb_write_called = TRUE; + wxUint32 a = segoffset(addr); + FRDP("FBWrite. addr: %08lx\n", a); + if (a < rdp.cimg || a > rdp.ci_end) + return; + cpu_fb_write = TRUE; + wxUint32 shift_l = (a-rdp.cimg) >> 1; + wxUint32 shift_r = shift_l+2; + + d_ul_x = min(d_ul_x, shift_l%rdp.ci_width); + d_ul_y = min(d_ul_y, shift_l/rdp.ci_width); + d_lr_x = max(d_lr_x, shift_r%rdp.ci_width); + d_lr_y = max(d_lr_y, shift_r/rdp.ci_width); +} + + +/************************************************************************ +Function: FBGetFrameBufferInfo +Purpose: This function is called by the emulator core to retrieve frame +buffer information from the video plugin in order to be able +to notify the video plugin about CPU frame buffer read/write +operations + +size: += 1 byte += 2 word (16 bit) <-- this is N64 default depth buffer format += 4 dword (32 bit) + +when frame buffer information is not available yet, set all values +in the FrameBufferInfo structure to 0 + +input: FrameBufferInfo pinfo[6] +pinfo is pointed to a FrameBufferInfo structure which to be +filled in by this function +output: Values are return in the FrameBufferInfo structure +Plugin can return up to 6 frame buffer info +************************************************************************/ +///* +#if 0 +typedef struct +{ + wxUint32 addr; + wxUint32 size; + wxUint32 width; + wxUint32 height; +} FrameBufferInfo; +#endif +EXPORT void CALL FBGetFrameBufferInfo(void *p) +{ + VLOG ("FBGetFrameBufferInfo ()\n"); + FrameBufferInfo * pinfo = (FrameBufferInfo *)p; + memset(pinfo,0,sizeof(FrameBufferInfo)*6); + if (!(settings.frame_buffer&fb_get_info)) + return; + LRDP("FBGetFrameBufferInfo ()\n"); + //* + if (fb_emulation_enabled) + { + pinfo[0].addr = rdp.maincimg[1].addr; + pinfo[0].size = rdp.maincimg[1].size; + pinfo[0].width = rdp.maincimg[1].width; + pinfo[0].height = rdp.maincimg[1].height; + int info_index = 1; + for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++) + { + COLOR_IMAGE & cur_fb = rdp.frame_buffers[i]; + if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self || + cur_fb.status == ci_old_copy) + { + pinfo[info_index].addr = cur_fb.addr; + pinfo[info_index].size = cur_fb.size; + pinfo[info_index].width = cur_fb.width; + pinfo[info_index].height = cur_fb.height; + info_index++; + } + } + } + else + { + pinfo[0].addr = rdp.maincimg[0].addr; + pinfo[0].size = rdp.ci_size; + pinfo[0].width = rdp.ci_width; + pinfo[0].height = rdp.ci_width*3/4; + pinfo[1].addr = rdp.maincimg[1].addr; + pinfo[1].size = rdp.ci_size; + pinfo[1].width = rdp.ci_width; + pinfo[1].height = rdp.ci_width*3/4; + } + //*/ +} +#ifdef __cplusplus +} +#endif +//*/ +#include "ucodeFB.h" + +void DetectFrameBufferUsage () +{ + LRDP("DetectFrameBufferUsage\n"); + + wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); + wxUint32 a; + + int tidal = FALSE; + if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) + tidal = TRUE; + wxUint32 ci = rdp.cimg, zi = rdp.zimg; + wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height; + rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; + rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0; + rdp.zimg_end = 0; + rdp.tmpzimg = 0; + rdp.motionblur = FALSE; + rdp.main_ci_last_tex_addr = 0; + int previous_ci_was_read = rdp.read_previous_ci; + rdp.read_previous_ci = FALSE; + rdp.read_whole_frame = FALSE; + rdp.swap_ci_index = rdp.black_ci_index = -1; + SwapOK = TRUE; + + // Start executing at the start of the display list + rdp.pc_i = 0; + rdp.pc[rdp.pc_i] = dlist_start; + rdp.dl_count = -1; + rdp.halt = 0; + rdp.scale_x_bak = rdp.scale_x; + rdp.scale_y_bak = rdp.scale_y; + + // MAIN PROCESSING LOOP + do { + + // Get the address of the next command + a = rdp.pc[rdp.pc_i] & BMASK; + + // Load the next command and its input + rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / + + // Output the address before the command + + // Go to the next instruction + rdp.pc[rdp.pc_i] = (a+8) & BMASK; + + if (wxPtrToUInt(reinterpret_cast(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))) + gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] (); + + // check DL counter + if (rdp.dl_count != -1) + { + rdp.dl_count --; + if (rdp.dl_count == 0) + { + rdp.dl_count = -1; + + LRDP("End of DL\n"); + rdp.pc_i --; + } + } + + } while (!rdp.halt); + SwapOK = TRUE; + if (rdp.ci_count > NUMTEXBUF) //overflow + { + rdp.cimg = ci; + rdp.zimg = zi; + rdp.num_of_ci = rdp.ci_count; + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + return; + } + + if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index) + rdp.frame_buffers[rdp.black_ci_index].status = ci_main; + + if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) + { + if (rdp.ci_count > 1) + rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; + else + rdp.frame_buffers[rdp.ci_count-1].status = ci_main; + } + + if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) && + (rdp.frame_buffers[rdp.main_ci_index].width < 320) && + (rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width)) + { + for (int i = 0; i < rdp.ci_count; i++) + { + if (rdp.frame_buffers[i].status == ci_main) + rdp.frame_buffers[i].status = ci_aux; + else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr) + rdp.frame_buffers[i].status = ci_main; + // FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status); + } + rdp.main_ci_index = rdp.ci_count-1; + } + + int all_zimg = TRUE; + int i; + for (i = 0; i < rdp.ci_count; i++) + { + if (rdp.frame_buffers[i].status != ci_zimg) + { + all_zimg = FALSE; + break; + } + } + if (all_zimg) + { + for (i = 0; i < rdp.ci_count; i++) + rdp.frame_buffers[i].status = ci_main; + } + + LRDP("detect fb final results: \n"); + for (i = 0; i < rdp.ci_count; i++) + { + FRDP("rdp.frame_buffers[%d].status = %s, addr: %08lx, height: %d\n", i, CIStatus[rdp.frame_buffers[i].status], rdp.frame_buffers[i].addr, rdp.frame_buffers[i].height); + } + + rdp.cimg = ci; + rdp.zimg = zi; + rdp.num_of_ci = rdp.ci_count; + if (rdp.read_previous_ci && previous_ci_was_read) + { + if (!fb_hwfbe_enabled || !rdp.copy_ci_index) + rdp.motionblur = TRUE; + } + if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy)) + { + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + } + + if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index) + rdp.read_whole_frame = TRUE; + if (rdp.read_whole_frame) + { + if (fb_hwfbe_enabled) + { + if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark)) + { + int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; + wxUint32 height = rdp.frame_buffers[ind].height; + rdp.frame_buffers[ind].height = ci_height; + CopyFrameBuffer(); + rdp.frame_buffers[ind].height = height; + } + if (rdp.swap_ci_index < 0) + { + rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE; + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + } + else + { + if (rdp.motionblur) + { + if (settings.frame_buffer&fb_motionblur) + CopyFrameBuffer(); + else + memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); + } + else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width) + { + if (rdp.maincimg[0].height > 65) //for 1080 + { + rdp.cimg = rdp.maincimg[0].addr; + rdp.ci_width = rdp.maincimg[0].width; + rdp.ci_count = 0; + wxUint32 h = rdp.frame_buffers[0].height; + rdp.frame_buffers[0].height = rdp.maincimg[0].height; + CopyFrameBuffer(); + rdp.frame_buffers[0].height = h; + } + else //conker + { + CopyFrameBuffer(); + } + } + } + } + + if (fb_hwfbe_enabled) + { + for (i = 0; i < voodoo.num_tmu; i++) + { + rdp.texbufs[i].clear_allowed = TRUE; + for (int j = 0; j < 256; j++) + { + rdp.texbufs[i].images[j].drawn = FALSE; + rdp.texbufs[i].images[j].clear = TRUE; + } + } + if (tidal) + { + //LRDP("Tidal wave!\n"); + rdp.copy_ci_index = rdp.main_ci_index; + } + } + rdp.ci_count = 0; + if (settings.hacks&hack_Banjo2) + rdp.cur_tex_buf = 0; + rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; + // rdp.scale_x = rdp.scale_x_bak; + // rdp.scale_y = rdp.scale_y_bak; + LRDP("DetectFrameBufferUsage End\n"); +} + +/******************************************* + * ProcessRDPList * + ******************************************* + * based on sources of ziggy's z64 * + *******************************************/ + +static wxUint32 rdp_cmd_ptr = 0; +static wxUint32 rdp_cmd_cur = 0; +static wxUint32 rdp_cmd_data[0x1000]; + +void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer, + wxUint32 * rdp_cmd) +{ + rdp.cur_tile = (w1 >> 16) & 0x7; + int j; + int xleft, xright, xleft_inc, xright_inc; + int r, g, b, a, z, s, t, w; + int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0; + int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0; + int flip = (w1 & 0x800000) ? 1 : 0; + + wxInt32 yl, ym, yh; + wxInt32 xl, xm, xh; + wxInt32 dxldy, dxhdy, dxmdy; + wxUint32 w3, w4, w5, w6, w7, w8; + + wxUint32 * shade_base = rdp_cmd + 8; + wxUint32 * texture_base = rdp_cmd + 8; + wxUint32 * zbuffer_base = rdp_cmd + 8; + + if (shade) + { + texture_base += 16; + zbuffer_base += 16; + } + if (texture) + { + zbuffer_base += 16; + } + + w3 = rdp_cmd[2]; + w4 = rdp_cmd[3]; + w5 = rdp_cmd[4]; + w6 = rdp_cmd[5]; + w7 = rdp_cmd[6]; + w8 = rdp_cmd[7]; + + yl = (w1 & 0x3fff); + ym = ((w2 >> 16) & 0x3fff); + yh = ((w2 >> 0) & 0x3fff); + xl = (wxInt32)(w3); + xh = (wxInt32)(w5); + xm = (wxInt32)(w7); + dxldy = (wxInt32)(w4); + dxhdy = (wxInt32)(w6); + dxmdy = (wxInt32)(w8); + + if (yl & (0x800<<2)) yl |= 0xfffff000<<2; + if (ym & (0x800<<2)) ym |= 0xfffff000<<2; + if (yh & (0x800<<2)) yh |= 0xfffff000<<2; + + yh &= ~3; + + r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000; + + if (shade) + { + r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff); + g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff); + b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff); + a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff); + drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff); + dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff); + dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff); + dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff); + drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff); + dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff); + dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff); + dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff); + } + if (texture) + { + s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff); + t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff); + w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff); + // w = abs(w); + dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff); + dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff); + dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff); + dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff); + dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff); + dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff); + } + if (zbuffer) + { + z = zbuffer_base[0]; + dzdx = zbuffer_base[1]; + dzde = zbuffer_base[2]; + } + + xh <<= 2; xm <<= 2; xl <<= 2; + r <<= 2; g <<= 2; b <<= 2; a <<= 2; + dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2; + dzdx >>= 2; dzde >>= 2; + dwdx >>= 2; dwde >>= 2; + +#define XSCALE(x) (float(x)/(1<<18)) +#define YSCALE(y) (float(y)/(1<<2)) +#define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000) + //#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f) + //#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f) +#define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f) +#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18) +#define _PERSP(w) ( w ) +#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) ) +#define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21)) +#define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21)) + + int nbVtxs = 0; + VERTEX vtxbuf[12]; + VERTEX * vtx = &vtxbuf[nbVtxs++]; + + xleft = xm; + xright = xh; + xleft_inc = dxmdy; + xright_inc = dxhdy; + + while (yh xright-0x10000))) { + xleft += xleft_inc; + xright += xright_inc; + s += dsde; t += dtde; w += dwde; + r += drde; g += dgde; b += dbde; a += dade; + z += dzde; + yh++; + } + + j = ym-yh; + if (j > 0) + { + int dx = (xleft-xright)>>16; + if ((!flip && xleft < xright) || + (flip/* && xleft > xright*/)) + { + if (shade) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (texture) { + vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(yh); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &vtxbuf[nbVtxs++]; + } + if ((!flip/* && xleft < xright*/) || + (flip && xleft > xright)) + { + if (shade) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (texture) { + vtx->ou = SSCALE(s, w); + vtx->ov = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(yh); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &vtxbuf[nbVtxs++]; + } + xleft += xleft_inc*j; xright += xright_inc*j; + s += dsde*j; t += dtde*j; + if (w + dwde*j) w += dwde*j; + else w += dwde*(j-1); + r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; + z += dzde*j; + // render ... + } + + if (xl != xh) + xleft = xl; + + //if (yl-ym > 0) + { + int dx = (xleft-xright)>>16; + if ((!flip && xleft <= xright) || + (flip/* && xleft >= xright*/)) + { + if (shade) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (texture) { + vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(ym); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &vtxbuf[nbVtxs++]; + } + if ((!flip/* && xleft <= xright*/) || + (flip && xleft >= xright)) + { + if (shade) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (texture) { + vtx->ou = SSCALE(s, w); + vtx->ov = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(ym); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &vtxbuf[nbVtxs++]; + } + } + xleft_inc = dxldy; + xright_inc = dxhdy; + + j = yl-ym; + //j--; // ? + xleft += xleft_inc*j; xright += xright_inc*j; + s += dsde*j; t += dtde*j; w += dwde*j; + r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; + z += dzde*j; + + while (yl>ym && + !((!flip && xleft < xright+0x10000) || + (flip && xleft > xright-0x10000))) { + xleft -= xleft_inc; xright -= xright_inc; + s -= dsde; t -= dtde; w -= dwde; + r -= drde; g -= dgde; b -= dbde; a -= dade; + z -= dzde; + j--; + yl--; + } + + // render ... + if (j >= 0) { + int dx = (xleft-xright)>>16; + if ((!flip && xleft <= xright) || + (flip/* && xleft >= xright*/)) + { + if (shade) { + vtx->r = CSCALE(r+drdx*dx); + vtx->g = CSCALE(g+dgdx*dx); + vtx->b = CSCALE(b+dbdx*dx); + vtx->a = CSCALE(a+dadx*dx); + } + if (texture) { + vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); + vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); + } + vtx->x = XSCALE(xleft); + vtx->y = YSCALE(yl); + vtx->z = ZSCALE(z+dzdx*dx); + vtx->w = WSCALE(w+dwdx*dx); + vtx = &vtxbuf[nbVtxs++]; + } + if ((!flip/* && xleft <= xright*/) || + (flip && xleft >= xright)) + { + if (shade) { + vtx->r = CSCALE(r); + vtx->g = CSCALE(g); + vtx->b = CSCALE(b); + vtx->a = CSCALE(a); + } + if (texture) { + vtx->ou = SSCALE(s, w); + vtx->ov = TSCALE(t, w); + } + vtx->x = XSCALE(xright); + vtx->y = YSCALE(yl); + vtx->z = ZSCALE(z); + vtx->w = WSCALE(w); + vtx = &vtxbuf[nbVtxs++]; + } + } + + if (fullscreen) + { + update (); + for (int k = 0; k < nbVtxs-1; k++) + { + VERTEX * v = &vtxbuf[k]; + v->x = v->x * rdp.scale_x + rdp.offset_x; + v->y = v->y * rdp.scale_y + rdp.offset_y; + // v->z = 1.0f;///v->w; + v->q = 1.0f/v->w; + v->u1 = v->u0 = v->ou; + v->v1 = v->v0 = v->ov; + if (rdp.tex >= 1 && rdp.cur_cache[0]) + { + if (rdp.tiles[rdp.cur_tile].shift_s) + { + if (rdp.tiles[rdp.cur_tile].shift_s > 10) + v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); + else + v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s); + } + if (rdp.tiles[rdp.cur_tile].shift_t) + { + if (rdp.tiles[rdp.cur_tile].shift_t > 10) + v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); + else + v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t); + } + + v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; + v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; + v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0; + v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0; + v->u0 /= v->w; + v->v0 /= v->w; + } + + if (rdp.tex >= 2 && rdp.cur_cache[1]) + { + if (rdp.tiles[rdp.cur_tile+1].shift_s) + { + if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) + v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); + else + v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s); + } + if (rdp.tiles[rdp.cur_tile+1].shift_t) + { + if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) + v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); + else + v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t); + } + + v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; + v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; + v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1; + v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1; + v->u1 /= v->w; + v->v1 /= v->w; + } + apply_shade_mods (v); + } + ConvertCoordsConvert (vtxbuf, nbVtxs); + grCullMode (GR_CULL_DISABLE); + grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX)); + if (_debugger.capture) + { + VERTEX vl[3]; + vl[0] = vtxbuf[0]; + vl[1] = vtxbuf[2]; + vl[2] = vtxbuf[1]; + add_tri (vl, 3, TRI_TRIANGLE); + rdp.tri_n++; + if (nbVtxs > 4) + { + vl[0] = vtxbuf[2]; + vl[1] = vtxbuf[3]; + vl[2] = vtxbuf[1]; + add_tri (vl, 3, TRI_TRIANGLE); + rdp.tri_n++; + } + } + } +} + +static void rdp_triangle(int shade, int texture, int zbuffer) +{ + lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur); +} + +static void rdp_trifill() +{ + rdp_triangle(0, 0, 0); + LRDP("trifill\n"); +} + +static void rdp_trishade() +{ + rdp_triangle(1, 0, 0); + LRDP("trishade\n"); +} + +static void rdp_tritxtr() +{ + rdp_triangle(0, 1, 0); + LRDP("tritxtr\n"); +} + +static void rdp_trishadetxtr() +{ + rdp_triangle(1, 1, 0); + LRDP("trishadetxtr\n"); +} + +static void rdp_trifillz() +{ + rdp_triangle(0, 0, 1); + LRDP("trifillz\n"); +} + +static void rdp_trishadez() +{ + rdp_triangle(1, 0, 1); + LRDP("trishadez\n"); +} + +static void rdp_tritxtrz() +{ + rdp_triangle(0, 1, 1); + LRDP("tritxtrz\n"); +} + +static void rdp_trishadetxtrz() +{ + rdp_triangle(1, 1, 1); + LRDP("trishadetxtrz\n"); +} + + +static rdp_instr rdp_command_table[64] = +{ + /* 0x00 */ + spnoop, undef, undef, undef, + undef, undef, undef, undef, + rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, + rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, + /* 0x10 */ + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + /* 0x20 */ + undef, undef, undef, undef, + rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, + rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, + rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, + /* 0x30 */ + rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, + rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, + rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, + rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage +}; + +static const wxUint32 rdp_command_length[64] = +{ + 8, // 0x00, No Op + 8, // 0x01, ??? + 8, // 0x02, ??? + 8, // 0x03, ??? + 8, // 0x04, ??? + 8, // 0x05, ??? + 8, // 0x06, ??? + 8, // 0x07, ??? + 32, // 0x08, Non-Shaded Triangle + 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle + 32+64, // 0x0a, Textured Triangle + 32+64+16, // 0x0b, Textured, Z-Buffered Triangle + 32+64, // 0x0c, Shaded Triangle + 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle + 32+64+64, // 0x0e, Shaded+Textured Triangle + 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle + 8, // 0x10, ??? + 8, // 0x11, ??? + 8, // 0x12, ??? + 8, // 0x13, ??? + 8, // 0x14, ??? + 8, // 0x15, ??? + 8, // 0x16, ??? + 8, // 0x17, ??? + 8, // 0x18, ??? + 8, // 0x19, ??? + 8, // 0x1a, ??? + 8, // 0x1b, ??? + 8, // 0x1c, ??? + 8, // 0x1d, ??? + 8, // 0x1e, ??? + 8, // 0x1f, ??? + 8, // 0x20, ??? + 8, // 0x21, ??? + 8, // 0x22, ??? + 8, // 0x23, ??? + 16, // 0x24, Texture_Rectangle + 16, // 0x25, Texture_Rectangle_Flip + 8, // 0x26, Sync_Load + 8, // 0x27, Sync_Pipe + 8, // 0x28, Sync_Tile + 8, // 0x29, Sync_Full + 8, // 0x2a, Set_Key_GB + 8, // 0x2b, Set_Key_R + 8, // 0x2c, Set_Convert + 8, // 0x2d, Set_Scissor + 8, // 0x2e, Set_Prim_Depth + 8, // 0x2f, Set_Other_Modes + 8, // 0x30, Load_TLUT + 8, // 0x31, ??? + 8, // 0x32, Set_Tile_Size + 8, // 0x33, Load_Block + 8, // 0x34, Load_Tile + 8, // 0x35, Set_Tile + 8, // 0x36, Fill_Rectangle + 8, // 0x37, Set_Fill_Color + 8, // 0x38, Set_Fog_Color + 8, // 0x39, Set_Blend_Color + 8, // 0x3a, Set_Prim_Color + 8, // 0x3b, Set_Env_Color + 8, // 0x3c, Set_Combine + 8, // 0x3d, Set_Texture_Image + 8, // 0x3e, Set_Mask_Image + 8 // 0x3f, Set_Color_Image +}; + +#define rdram ((wxUint32*)gfx.RDRAM) +#define rsp_dmem ((wxUint32*)gfx.DMEM) + +#define dp_start (*(wxUint32*)gfx.DPC_START_REG) +#define dp_end (*(wxUint32*)gfx.DPC_END_REG) +#define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG) +#define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG) + +inline wxUint32 READ_RDP_DATA(wxUint32 address) +{ + if (dp_status & 0x1) // XBUS_DMEM_DMA enabled + return rsp_dmem[(address & 0xfff)>>2]; + else + return rdram[address>>2]; +} + +static void rdphalf_1() +{ + wxUint32 cmd = rdp.cmd1 >> 24; + if (cmd >= 0xc8 && cmd <=0xcf) //triangle command + { + LRDP("rdphalf_1 - lle triangle\n"); + rdp_cmd_ptr = 0; + rdp_cmd_cur = 0; + wxUint32 a; + + do + { + rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; + // check DL counter + if (rdp.dl_count != -1) + { + rdp.dl_count --; + if (rdp.dl_count == 0) + { + rdp.dl_count = -1; + + LRDP("End of DL\n"); + rdp.pc_i --; + } + } + + // Get the address of the next command + a = rdp.pc[rdp.pc_i] & BMASK; + + // Load the next command and its input + rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / + + // Go to the next instruction + rdp.pc[rdp.pc_i] = (a+8) & BMASK; + + }while ((rdp.cmd0 >> 24) != 0xb3); + rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; + cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; + rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; + rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; + /* + wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2]; + if ((cmd3>>24) == 0xb4) + rglSingleTriangle = TRUE; + else + rglSingleTriangle = FALSE; + */ + rdp_command_table[cmd](); + } + else + { + LRDP("rdphalf_1 - IGNORED\n"); + } +} + +static void rdphalf_2() +{ + RDP_E("rdphalf_2 - IGNORED\n"); + LRDP("rdphalf_2 - IGNORED\n"); +} + +static void rdphalf_cont() +{ + RDP_E("rdphalf_cont - IGNORED\n"); + LRDP("rdphalf_cont - IGNORED\n"); +} + +/****************************************************************** +Function: ProcessRDPList +Purpose: This function is called when there is a Dlist to be +processed. (Low level GFX list) +input: none +output: none +*******************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif +EXPORT void CALL ProcessRDPList(void) +{ + LOG ("ProcessRDPList ()\n"); + LRDP("ProcessRDPList ()\n"); + + SoftLocker lock(mutexProcessDList); + if (!lock.IsOk()) //mutex is busy + { + if (!fullscreen) + drawNoFullscreenMessage(); + // Set an interrupt to allow the game to continue + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + return; + } + + wxUint32 i; + wxUint32 cmd, length, cmd_length; + rdp_cmd_ptr = 0; + rdp_cmd_cur = 0; + + if (dp_end <= dp_current) return; + length = dp_end - dp_current; + + // load command data + for (i=0; i < length; i += 4) + { + rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i); + if (rdp_cmd_ptr >= 0x1000) + { + FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end); + } + } + + dp_current = dp_end; + + cmd = (rdp_cmd_data[0] >> 24) & 0x3f; + cmd_length = (rdp_cmd_ptr + 1) * 4; + + // check if more data is needed + if (cmd_length < rdp_command_length[cmd]) + return; + rdp.LLE = TRUE; + while (rdp_cmd_cur < rdp_cmd_ptr) + { + cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; + + if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd]) + return; + + // execute the command + rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; + rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; + rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2]; + rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3]; + rdp_command_table[cmd](); + + rdp_cmd_cur += rdp_command_length[cmd] / 4; + }; + rdp.LLE = FALSE; + + dp_start = dp_end; + + dp_status &= ~0x0002; + + //} +} + +#ifdef __cplusplus +} +#endif +