Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/Main.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation; either version 2 of the License, or7* any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*14* You should have received a copy of the GNU General Public15* Licence along with this program; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,17* Boston, MA 02110-1301, USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)23// Project started on December 29th, 200124//25// To modify Glide64:26// * 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.27// * 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.28//29// Official Glide64 development channel: #Glide64 on EFnet30//31// Original author: Dave2001 ([email protected])32// Other authors: Gonetz, Gugaman33//34//****************************************************************3536#include "Util.h"37#include "3dmath.h"38#include "Debugger.h"3940#include "Combine.h"4142#include "Ini.h"43#include "Config.h"4445#include "TexCache.h"46#include "CRC.h"47#include "DepthBufferRender.h"4849#include <string.h>50#include <stdlib.h>5152#ifndef _WIN3253#include <sys/time.h>54#endif5556#include "osal_dynamiclib.h"5758#define G64_VERSION "Mupen64Plus"59#define RELTIME "Date: " __DATE__ " Time: " __TIME__6061#ifdef EXT_LOGGING62std::ofstream extlog;63#endif6465#ifdef LOGGING66std::ofstream loga;67#endif6869#ifdef RDP_LOGGING70BOOL log_open = FALSE;71std::ofstream rdp_log;72#endif7374#ifdef RDP_ERROR_LOG75BOOL elog_open = FALSE;76std::ofstream rdp_err;77#endif7879GFX_INFO gfx;80/* definitions of pointers to Core config functions */81ptr_ConfigOpenSection ConfigOpenSection = NULL;82ptr_ConfigSetParameter ConfigSetParameter = NULL;83ptr_ConfigGetParameter ConfigGetParameter = NULL;84ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;85ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL;86ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL;87ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL;88ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;89ptr_ConfigGetParamInt ConfigGetParamInt = NULL;90ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL;91ptr_ConfigGetParamBool ConfigGetParamBool = NULL;92ptr_ConfigGetParamString ConfigGetParamString = NULL;9394ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;95ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;96ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;97ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;9899/* definitions of pointers to Core video extension functions */100ptr_VidExt_Init CoreVideo_Init = NULL;101ptr_VidExt_Quit CoreVideo_Quit = NULL;102ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL;103ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL;104ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL;105ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL;106ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL;107ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL;108ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL;109ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL;110111BOOL to_fullscreen = FALSE;112BOOL fullscreen = FALSE;113BOOL romopen = FALSE;114GrContext_t gfx_context = 0;115BOOL debugging = FALSE;116HINSTANCE hInstance = NULL;117BOOL exception = FALSE;118119BOOL evoodoo = 0;120BOOL ev_fullscreen = 0;121122int num_tmu;123int max_tex_size;124long sup_mirroring;125BOOL sup_32bit_tex = FALSE;126127#ifdef ALTTAB_FIX128HHOOK hhkLowLevelKybd = NULL;129LRESULT CALLBACK LowLevelKeyboardProc(int nCode,130WPARAM wParam, LPARAM lParam);131#endif132133#ifdef PERFORMANCE134__int64 perf_cur;135__int64 perf_next;136#endif137138#ifdef FPS139LARGE_INTEGER perf_freq;140LARGE_INTEGER fps_last;141LARGE_INTEGER fps_next;142float fps = 0.0f;143DWORD fps_count = 0;144145DWORD vi_count = 0;146float vi = 0.0f;147148DWORD region = 0;149150float ntsc_percent = 0.0f;151float pal_percent = 0.0f;152153#endif154155// Resolutions, MUST be in the correct order (SST1VID.H)156DWORD resolutions[0x18][2] = {157{ 320, 200 },158{ 320, 240 },159{ 400, 256 },160{ 512, 384 },161{ 640, 200 },162{ 640, 350 },163{ 640, 400 },164{ 640, 480 },165{ 800, 600 },166{ 960, 720 },167{ 856, 480 },168{ 512, 256 },169{ 1024, 768 },170{ 1280, 1024 },171{ 1600, 1200 },172{ 400, 300 },173174// 0x10175{ 1152, 864 },176{ 1280, 960 },177{ 1600, 1024 },178{ 1792, 1344 },179{ 1856, 1392 },180{ 1920, 1440 },181{ 2048, 1536 },182{ 2048, 2048 }183};184185enum {186NONE,187ZELDA,188BOMBERMAN64,189DIDDY,190TONIC,191ASB,192DORAEMON2,193INVADERS,194BAR,195ISS64,196RE2,197NITRO,198CHOPPER,199YOSHI,200FZERO,201PM,202TGR,203TGR2,204KI,205LEGO206};207208// ref rate209// 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff210211unsigned long BMASK = 0x7FFFFF;212// Reality display processor structure213RDP rdp;214215SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };216217HOTKEY_INFO hotkey_info;218219GrTexInfo fontTex;220GrTexInfo cursorTex;221DWORD offset_font = 0;222DWORD offset_cursor = 0;223DWORD offset_textures = 0;224DWORD offset_texbuf1 = 0;225226BOOL capture_screen = 0;227char capture_path[256];228229void (*renderCallback)(int) = NULL;230static void (*l_DebugCallback)(void *, int, const char *) = NULL;231static void *l_DebugCallContext = NULL;232233234void WriteLog(m64p_msg_level level, const char *msg, ...)235{236char buf[1024];237va_list args;238va_start(args, msg);239vsnprintf(buf, 1023, msg, args);240buf[1023]='\0';241va_end(args);242if (l_DebugCallback)243{244l_DebugCallback(l_DebugCallContext, level, buf);245}246}247248void ChangeSize ()249{250float res_scl_x = (float)settings.res_x / 320.0f;251float res_scl_y = (float)settings.res_y / 240.0f;252253DWORD scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;254if (!scale_x) return;255DWORD scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF;256if (!scale_y) return;257258float fscale_x = (float)scale_x / 1024.0f;259float fscale_y = (float)scale_y / 1024.0f;260261DWORD dwHStartReg = *gfx.VI_H_START_REG;262DWORD dwVStartReg = *gfx.VI_V_START_REG;263264DWORD hstart = dwHStartReg >> 16;265DWORD hend = dwHStartReg & 0xFFFF;266267// dunno... but sometimes this happens268if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);269270DWORD vstart = dwVStartReg >> 16;271DWORD vend = dwVStartReg & 0xFFFF;272273sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);274LOG (out_buf);275276rdp.vi_width = (hend - hstart) * fscale_x;277rdp.vi_height = (vend - vstart)/2 * fscale_y;278279sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);280LOG (out_buf);281282if (region == 0)283{284if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2285{286rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);287rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);288}289else290{291rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);292rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);293}294}295else296{297// odd... but pal games seem to want 230 as height...298if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2299{300// NOT SURE ABOUT PAL HERE, DON'T HAVE PAL MEGAMAN TO TRY301rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);302// VP changed to 120303rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);304//rdp.scale_y = res_scl_y * (115.0f / rdp.vi_height);305}306else307{308rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);309// VP changed to 240310rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);311//rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height);312}313}314315rdp.offset_x = settings.offset_x * res_scl_x;316rdp.offset_y = settings.offset_y * res_scl_y;317if (settings.scale_x != 0)318rdp.scale_x *= (settings.scale_x / 100000.0f);319if (settings.scale_y != 0)320rdp.scale_y *= (settings.scale_y / 100000.0f);321322rdp.scale_1024 = settings.scr_res_x / 1024.0f;323rdp.scale_768 = settings.scr_res_y / 768.0f;324325rdp.scissor_o.ul_x = 0;326rdp.scissor_o.ul_y = 0;327rdp.scissor_o.lr_x = (DWORD)rdp.vi_width;328rdp.scissor_o.lr_y = (DWORD)rdp.vi_height;329330rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;331}332333void ReadSettings ()334{335// LOG("ReadSettings\n");336if (!Config_Open())337{338WriteLog(M64MSG_ERROR, "Could not open configuration!");339return;340}341settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE);342343settings.depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE);344PackedScreenResolution packedResolution = Config_ReadScreenSettings();345settings.res_data = (DWORD) packedResolution.resolution;346settings.scr_res_x = settings.res_x = packedResolution.width;347settings.scr_res_y = settings.res_y = packedResolution.height;348settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1);349settings.ucode = (DWORD)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE);350351settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0);352settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE);353settings.filtering = (BYTE)Config_ReadInt ("filtering", "Filtering mode: 0=None, 1=Force bilinear, 2=Force point-sampled", 1, TRUE, FALSE);354settings.fog = (BOOL)Config_ReadInt ("fog", "Fog enabled", 1);355settings.buff_clear = (BOOL)Config_ReadInt ("buff_clear", "Buffer clear on every frame", 1);356settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0);357settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0);358settings.swapmode = (BYTE)Config_ReadInt ("swapmode", "Buffer swapping method: 0=Old, 1=New, 2=Hybrid", 1, TRUE, FALSE);359settings.lodmode = (BYTE)Config_ReadInt ("lodmode", "LOD calculation: 0=Off, 1=Fast, 2=Precise", 0, TRUE, FALSE);360361settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);362settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);363settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0);364settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0);365settings.cpu_write_hack = (BOOL)Config_ReadInt ("detect_cpu_write", "Detect CPU writes", 0);366settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0);367settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0);368settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0);369370settings.wrap_big_tex = (BOOL)Config_ReadInt ("wrap_big_tex", "Wrap textures too big for tmem", 0);371settings.flame_corona = (BOOL)Config_ReadInt ("flame_corona", "Zelda corona fix", 0);372// settings.RE2_native_video = (BOOL)INI_ReadInt ("RE2_native_video", 0);373374settings.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);375376settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0);377settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0);378379settings.fb_read_always = (BOOL)Config_ReadInt ("fb_read_always", "Framebuffer read every frame", 0);380settings.fb_read_alpha = (BOOL)Config_ReadInt ("fb_read_alpha", "Framebuffer read alpha", 0);381settings.fb_smart = (BOOL)Config_ReadInt ("fb_smart", "Smart framebuffer", 0);382settings.fb_motionblur = (BOOL)Config_ReadInt ("motionblur", "Motion blur", 0);383settings.fb_hires = (BOOL)Config_ReadInt ("fb_hires", "Hi-res framebuffer", 1);384settings.fb_get_info = (BOOL)Config_ReadInt ("fb_get_info", "Get framebuffer info", 0);385settings.fb_depth_clear = (BOOL)Config_ReadInt ("fb_clear", "Clear framebuffer", 0);386settings.fb_depth_render = (BOOL)Config_ReadInt ("fb_render", "Depth buffer render", 0);387if (settings.fb_depth_render)388settings.fb_depth_clear = TRUE;389390settings.custom_ini = (BOOL)Config_ReadInt ("custom_ini", "Use custom INI settings", 0);391settings.hotkeys = 0;392393settings.full_res = 0;394settings.tex_filter = (DWORD)Config_ReadInt ("tex_filter", "Texture filter: 0=None, 1=Blur edges, 2=Super 2xSai, 3=Hq2x, 4=Hq4x", 0, TRUE, FALSE);395settings.noditheredalpha = (BOOL)Config_ReadInt ("noditheredalpha", "Disable dithered alpha", 1);396settings.noglsl = (BOOL)Config_ReadInt ("noglsl", "Disable GLSL combiners", 1);397settings.FBO = (BOOL)Config_ReadInt ("fbo", "Use framebuffer objects", 0);398settings.disable_auxbuf = (BOOL)Config_ReadInt ("disable_auxbuf", "Disable aux buffer", 0);399400}401402void ReadSpecialSettings (const char name[21])403{404// char buf [256];405// sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);406// LOG(buf);407settings.zelda = FALSE; //zeldas hacks408settings.bomberman64 = FALSE; //bomberman64 hacks409settings.diddy = FALSE; //diddy kong racing410settings.tonic = FALSE; //tonic trouble411settings.PPL = FALSE; //pokemon puzzle league requires many special fixes412settings.ASB = FALSE; //All-Star Baseball games413settings.doraemon2 = FALSE;//Doraemon 2414settings.invaders = FALSE; //Space Invaders415settings.BAR = FALSE; //Beetle Adventure Racing416settings.ISS64 = FALSE; //International Superstar Soccer 64417settings.RE2 = FALSE; //Resident Evil 2418settings.nitro = FALSE; //WCW Nitro419settings.chopper = FALSE; //Chopper Attack420settings.yoshi = FALSE; // Yoshi Story421settings.fzero = FALSE; // F-Zero422settings.PM = FALSE; //Paper Mario423settings.TGR = FALSE; //Top Gear Rally424settings.TGR2 = FALSE; //Top Gear Rally 2425settings.KI = FALSE; //Killer Instinct426settings.lego = FALSE; //LEGO Racers427428//detect games which require special hacks429if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))430settings.zelda = TRUE;431else if (strstr(name, (const char *)"ROADSTERS TROPHY"))432settings.zelda = TRUE;433else if (strstr(name, (const char *)"Diddy Kong Racing"))434settings.diddy = TRUE;435else if (strstr(name, (const char *)"BOMBERMAN64"))436settings.bomberman64 = TRUE;437else if (strstr(name, (const char *)"BAKU-BOMBERMAN"))438settings.bomberman64 = TRUE;439else if (strstr(name, (const char *)"Tonic Trouble"))440settings.tonic = TRUE;441else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))442settings.ASB = TRUE;443else if (strstr(name, (const char *)"\xbf\xef\xef\xbd\xbd\xbf\xb4\xd7\xbf\xef\xef\xbd\xbd\xbf\x20\x32\xb6\xcb\xbf\xef\xc9\xbd\xef\xbc\xbd\xbf\xbf\xef\xef\xbd\xbd\xbf\xbf\xef\x0a\xbd"))444settings.doraemon2 = TRUE;445else if (strstr(name, (const char *)"SPACE INVADERS"))446settings.invaders = TRUE;447else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))448settings.BAR = TRUE;449else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"PERFECT STRIKER"))450settings.ISS64 = TRUE;451else if (strstr(name, (const char *)"NITRO64"))452settings.nitro = TRUE;453else if (strstr(name, (const char *)"CHOPPER_ATTACK"))454settings.chopper = TRUE;455else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))456{457settings.RE2 = TRUE;458ZLUT_init();459}460else if (strstr(name, (const char *)"YOSHI STORY"))461settings.yoshi= TRUE;462else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))463settings.fzero = TRUE;464else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))465settings.PM = TRUE;466else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))467settings.TGR2 = TRUE;468else if (strstr(name, (const char *)"TOP GEAR RALLY"))469settings.TGR = TRUE;470else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))471settings.KI = TRUE;472else if (strstr(name, (const char *)"LEGORacers"))473settings.lego = TRUE;474475int EnableHacksForGame = (int)Config_ReadInt ("enable_hacks_for_game", "???", 0, TRUE, FALSE);476477switch (EnableHacksForGame)478{479case ZELDA:480settings.zelda = TRUE;481break;482case BOMBERMAN64:483settings.bomberman64 = TRUE;484break;485case DIDDY:486settings.diddy = TRUE;487break;488case TONIC:489settings.tonic = TRUE;490break;491case ASB:492settings.ASB = TRUE;493break;494case DORAEMON2:495settings.doraemon2 = TRUE;496break;497case INVADERS:498settings.invaders = TRUE;499break;500case BAR:501settings.BAR = TRUE;502break;503case ISS64:504settings.ISS64 = TRUE;505break;506case RE2:507settings.RE2 = TRUE;508ZLUT_init();509break;510case NITRO:511settings.nitro = TRUE;512break;513case CHOPPER:514settings.chopper = TRUE;515break;516case YOSHI:517settings.yoshi= TRUE;518break;519case FZERO:520settings.fzero = TRUE;521break;522case PM:523settings.PM = TRUE;524break;525case TGR:526settings.TGR = TRUE;527break;528case TGR2:529settings.TGR2 = TRUE;530break;531case KI:532settings.KI = TRUE;533break;534case LEGO:535settings.lego = TRUE;536break;537}538539540settings.offset_x = (int)Config_ReadInt ("offset_x", "???", 0, TRUE, FALSE);541settings.offset_y = (int)Config_ReadInt ("offset_y", "???", 0, TRUE, FALSE);542settings.scale_x = (int)Config_ReadInt ("scale_x", "???", 100000, TRUE, FALSE);543settings.scale_y = (int)Config_ReadInt ("scale_y", "???", 100000, TRUE, FALSE);544settings.alt_tex_size = (BOOL)Config_ReadInt ("alt_tex_size", "???", 0);545settings.use_sts1_only = (BOOL)Config_ReadInt ("use_sts1_only", "???", 0);546settings.PPL = (BOOL)Config_ReadInt ("PPL", "???", 0);547settings.fb_optimize_texrect = (BOOL)Config_ReadInt ("fb_optimize_texrect", "???", 1);548settings.fb_optimize_write = (BOOL)Config_ReadInt ("fb_optimize_write", "???", 0);549settings.fb_ignore_aux_copy = (BOOL)Config_ReadInt ("fb_ignore_aux_copy", "???", 0);550settings.fb_hires_buf_clear = (BOOL)Config_ReadInt ("fb_hires_buf_clear", "???", 1);551settings.wrap_big_tex = (BOOL)Config_ReadInt ("wrap_big_tex", "???", 0);552settings.fix_tex_coord = (BOOL)Config_ReadInt ("fix_tex_coord", "???", 0);553settings.soft_depth_compare = (BOOL)Config_ReadInt ("soft_depth_compare", "???", 0);554settings.force_depth_compare = (BOOL)Config_ReadInt ("force_depth_compare", "???", 0);555settings.fillcolor_fix = (BOOL)Config_ReadInt ("fillcolor_fix", "???", 0);556settings.depth_bias = -(int)Config_ReadInt ("depth_bias", "???", 20, TRUE, FALSE);557settings.increase_texrect_edge = (BOOL)Config_ReadInt ("increase_texrect_edge", "???", 0);558settings.decrease_fillrect_edge = (BOOL)Config_ReadInt ("decrease_fillrect_edge", "???", 0);559settings.increase_primdepth = (BOOL)Config_ReadInt ("increase_primdepth", "???", 0);560settings.stipple_mode = (int)Config_ReadInt ("stipple_mode", "???", 1, TRUE, FALSE);561settings.stipple_pattern = (DWORD)Config_ReadInt ("stipple_pattern", "???", 1041204192, TRUE, FALSE);562settings.force_microcheck = (BOOL)Config_ReadInt ("force_microcheck", "???", 0);563settings.fb_ignore_previous = (BOOL)Config_ReadInt ("fb_ignore_previous", "???", 0);564settings.fb_get_info = (BOOL)Config_ReadInt ("fb_get_info", "???", 0);565settings.fb_hires = (BOOL)Config_ReadInt ("fb_hires", "???", 0);566567settings.lodmode = (int)Config_ReadInt ("lodmode", "???", 0, TRUE, FALSE);568569settings.filtering = (int)Config_ReadInt ("filtering", "???", 1, TRUE, FALSE);570settings.fog = (int)Config_ReadInt ("fog", "???", 1, TRUE, FALSE);571settings.buff_clear = (BOOL)Config_ReadInt ("buff_clear", "???", 1);572settings.swapmode = (int)Config_ReadInt ("swapmode", "???", 1, TRUE, FALSE);573settings.fb_smart = (BOOL)Config_ReadInt ("fb_smart", "???", 0);574settings.fb_read_alpha = (BOOL)Config_ReadInt ("fb_read_alpha", "???", 0);575settings.fb_depth_clear = (BOOL)Config_ReadInt ("fb_depth_clear", "???", 0);576settings.cpu_write_hack = (BOOL)Config_ReadInt ("cpu_write_hack", "???", 0);577578if (settings.fb_depth_render)579settings.fb_depth_clear = TRUE;580INI_Close ();581}582583#include "font.h"584#include "cursor.h"585586GRFRAMEBUFFERCOPYEXT grFramebufferCopyExt = NULL;587GRTEXBUFFEREXT grTextureBufferExt = NULL;588GRTEXBUFFEREXT grTextureAuxBufferExt = NULL;589GRAUXBUFFEREXT grAuxBufferExt = NULL;590GRSTIPPLE grStippleModeExt = NULL;591GRSTIPPLE grStipplePatternExt = NULL;592BOOL combineext = FALSE;593594BOOL depthbuffersave = FALSE;595596// guLoadTextures - used to load the cursor and font textures597void guLoadTextures ()598{599if (grTextureBufferExt)600{601int tbuf_size = 0;602if (max_tex_size <= 256)603{604grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_256, GR_LOD_LOG2_256,605GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );606tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256,607GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);608}609else if (settings.scr_res_x <= 1024)610{611grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,612GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );613tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,614GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);615}616else617{618grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,619GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );620tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,621GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);622}623624//tbuf_size *= 2;625WriteLog(M64MSG_INFO, "tbuf_size %gMb\n", tbuf_size/1024.0f/1024);626rdp.texbufs[0].tmu = GR_TMU0;627rdp.texbufs[0].begin = grTexMinAddress(GR_TMU0);628rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;629rdp.texbufs[0].count = 0;630rdp.texbufs[0].clear_allowed = TRUE;631if (num_tmu > 1)632{633rdp.texbufs[1].tmu = GR_TMU1;634rdp.texbufs[1].begin = grTexMinAddress(GR_TMU1);635rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;636rdp.texbufs[1].count = 0;637rdp.texbufs[1].clear_allowed = TRUE;638offset_texbuf1 = tbuf_size;639}640offset_font = tbuf_size;641}642else643offset_font = 0;644645DWORD *data = (DWORD*)font;646DWORD cur;647648// ** Font texture **649BYTE *tex8 = (BYTE*)malloc(256*64);650651fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;652fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;653fontTex.format = GR_TEXFMT_ALPHA_8;654fontTex.data = tex8;655656// Decompression: [1-bit inverse alpha --> 8-bit alpha]657DWORD i,b;658for (i=0; i<0x200; i++)659{660// cur = ~*(data++), byteswapped661#if !defined(__GNUC__)662cur = _byteswap_ulong(~*(data++));663#else664cur = __builtin_bswap32(~*(data++));665#endif666667for (b=0x80000000; b!=0; b>>=1)668{669if (cur&b) *tex8 = 0xFF;670else *tex8 = 0x00;671tex8 ++;672}673}674675grTexDownloadMipMap (GR_TMU0,676grTexMinAddress(GR_TMU0) + offset_font,677GR_MIPMAPLEVELMASK_BOTH,678&fontTex);679680offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);681682free (fontTex.data);683684// ** Cursor texture **685data = (DWORD*)cursor;686687WORD *tex16 = (WORD*)malloc(32*32*2);688689cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32;690cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;691cursorTex.format = GR_TEXFMT_ARGB_1555;692cursorTex.data = tex16;693694// Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]695for (i=0; i<0x200; i++)696{697cur = *(data++);698*(tex16++) = (WORD)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));699*(tex16++) = (WORD)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));700}701702grTexDownloadMipMap (GR_TMU0,703grTexMinAddress(GR_TMU0) + offset_cursor,704GR_MIPMAPLEVELMASK_BOTH,705&cursorTex);706707// Round to higher 16708offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))709& 0xFFFFFFF0) + 16;710free (cursorTex.data);711}712713714BOOL InitGfx (BOOL evoodoo_using_window)715{716if (fullscreen)717{718ReleaseGfx ();719}720721OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it722OPEN_RDP_E_LOG ();723LOG ("InitGfx ()\n");724725debugging = FALSE;726727// Initialize Glide728grGlideInit ();729730// Select the Glide device731grSstSelect (settings.card_id);732733gfx_context = 0;734// Select the window735736if (settings.fb_hires)737{738WriteLog(M64MSG_INFO, "fb_hires\n");739GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress("grSstWinOpenExt");740if (grSstWinOpenExt)741gfx_context = grSstWinOpenExt ((FxU32)NULL,742settings.res_data,743GR_REFRESH_60Hz,744GR_COLORFORMAT_RGBA,745GR_ORIGIN_UPPER_LEFT,746GR_PIXFMT_RGB_565,7472, // Double-buffering7481); // 1 auxillary buffer749}750if (!gfx_context)751gfx_context = grSstWinOpen ((FxU32)NULL,752settings.res_data,753GR_REFRESH_60Hz,754GR_COLORFORMAT_RGBA,755GR_ORIGIN_UPPER_LEFT,7562, // Double-buffering7571); // 1 auxillary buffer758759if (!gfx_context)760{761WriteLog(M64MSG_ERROR, "Error setting display mode");762grSstWinClose (gfx_context);763grGlideShutdown ();764return FALSE;765}766767// get the # of TMUs available768grGet (GR_NUM_TMU, 4, (FxI32 *) &num_tmu);769WriteLog(M64MSG_INFO, "num_tmu %d\n", num_tmu);770// get maximal texture size771grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32 *) &max_tex_size);772//num_tmu = 1;773774// Is mirroring allowed?775const char *extensions = grGetString (GR_EXTENSION);776777if (strstr (extensions, "TEXMIRROR"))778sup_mirroring = 1;779else780sup_mirroring = 0;781782if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension783sup_32bit_tex = TRUE;784else785sup_32bit_tex = FALSE;786787if (settings.fb_hires)788{789const char * extstr = strstr(extensions, "TEXTUREBUFFER");790if (extstr)791{792if (!strncmp(extstr, "TEXTUREBUFFER", 13))793{794grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureBufferExt");795grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureAuxBufferExt");796grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress("grAuxBufferExt");797}798}799else800settings.fb_hires = 0;801}802else803grTextureBufferExt = 0;804805grFramebufferCopyExt = (GRFRAMEBUFFERCOPYEXT) grGetProcAddress("grFramebufferCopyExt");806grStippleModeExt = (GRSTIPPLE) grStippleMode;807grStipplePatternExt = (GRSTIPPLE) grStipplePattern;808if (grStipplePatternExt)809grStipplePatternExt(settings.stipple_pattern);810811InitCombine();812813#ifdef SIMULATE_VOODOO1814num_tmu = 1;815sup_mirroring = 0;816#endif817818#ifdef SIMULATE_BANSHEE819num_tmu = 1;820sup_mirroring = 1;821#endif822823fullscreen = TRUE;824825if (evoodoo_using_window)826ev_fullscreen = FALSE;827else828ev_fullscreen = TRUE;829830grCoordinateSpace (GR_WINDOW_COORDS);831grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE);832grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE);833grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE);834grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE);835grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE);836grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE);837838grCullMode(GR_CULL_NEGATIVE);839840if (settings.fog) //"FOGCOORD" extension841{842if (strstr (extensions, "FOGCOORD"))843{844GrFog_t fog_t[64];845guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);846847for (int i = 63; i > 0; i--)848{849if (fog_t[i] - fog_t[i-1] > 63)850{851fog_t[i-1] = fog_t[i] - 63;852}853}854fog_t[0] = 0;855// for (int f = 0; f < 64; f++)856// {857// FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));858// }859grFogTable (fog_t);860grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);861}862else //not supported863settings.fog = FALSE;864}865866//grDepthBufferMode (GR_DEPTHBUFFER_WBUFFER);867grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);868grDepthBufferFunction(GR_CMP_LESS);869grDepthMask(FXTRUE);870871settings.res_x = settings.scr_res_x;872settings.res_y = settings.scr_res_y;873ChangeSize ();874875guLoadTextures ();876grRenderBuffer(GR_BUFFER_BACKBUFFER);877878rdp_reset ();879ClearCache ();880881rdp.update |= UPDATE_SCISSOR;882883return TRUE;884}885886void ReleaseGfx ()887{888// Release graphics889grSstWinClose (gfx_context);890891// Shutdown glide892grGlideShutdown();893894fullscreen = FALSE;895rdp.window_changed = TRUE;896}897898#ifdef __cplusplus899extern "C" {900#endif901902EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)903{904*width = settings.res_x;905*height = settings.res_y;906if (dest)907{908BYTE * line = (BYTE*)dest;909if (!fullscreen)910{911for (DWORD y=0; y<settings.res_y; y++)912{913for (DWORD x=0; x<settings.res_x; x++)914{915line[x*3] = 0x20;916line[x*3+1] = 0x7f;917line[x*3+2] = 0x40;918}919}920WriteLog(M64MSG_WARNING, "[Glide64] Cannot save screenshot in windowed mode?\n");921return;922}923924GrLfbInfo_t info;925info.size = sizeof(GrLfbInfo_t);926if (grLfbLock(GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER, GR_LFBWRITEMODE_888, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))927{928// Copy the screen929for (DWORD y=0; y<settings.res_y; y++)930{931BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);932for (DWORD x=0; x<settings.res_x; x++)933{934line[x*4+2] = ptr[2]; // red935line[x*4+1] = ptr[1]; // green936line[x*4] = ptr[0]; // blue937ptr += 4;938}939line += settings.res_x * 4;940}941942// Unlock the frontbuffer943grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);944}945LOG ("ReadScreen. Success.\n");946}947}948949EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,950void (*DebugCallback)(void *, int, const char *))951{952l_DebugCallback = DebugCallback;953l_DebugCallContext = Context;954955/* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */956ptr_CoreGetAPIVersions CoreAPIVersionFunc;957CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");958if (CoreAPIVersionFunc == NULL)959{960WriteLog(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");961return M64ERR_INCOMPATIBLE;962}963int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;964(*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);965if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))966{967WriteLog(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with %s (v%i.%i.%i)",968VERSION_PRINTF_SPLIT(ConfigAPIVersion), PLUGIN_NAME, VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));969return M64ERR_INCOMPATIBLE;970}971if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))972{973WriteLog(M64MSG_ERROR, "Emulator core Video Extension API (v%i.%i.%i) incompatible with %s (v%i.%i.%i)",974VERSION_PRINTF_SPLIT(VidextAPIVersion), PLUGIN_NAME, VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION));975return M64ERR_INCOMPATIBLE;976}977978/* Get the core config function pointers from the library handle */979ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");980ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");981ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");982ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");983ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");984ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");985ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");986ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");987ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");988ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");989ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");990991ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");992ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");993ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");994ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");995996if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||997!ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||998!ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||999!ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)1000{1001WriteLog(M64MSG_ERROR, "Couldn't connect to Core configuration functions");1002return M64ERR_INCOMPATIBLE;1003}10041005/* Get the core Video Extension function pointers from the library handle */1006CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");1007CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");1008CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");1009CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");1010CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");1011CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");1012CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");1013CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");1014CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");1015CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");10161017if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||1018!CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress ||1019!CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers || !CoreVideo_ResizeWindow)1020{1021WriteLog(M64MSG_ERROR, "Couldn't connect to Core video functions");1022return M64ERR_INCOMPATIBLE;1023}10241025const char *configDir = ConfigGetSharedDataFilepath("Glide64.ini");1026if (configDir)1027{1028SetConfigDir(configDir);1029ReadSettings();1030return M64ERR_SUCCESS;1031}1032else1033{1034WriteLog(M64MSG_ERROR, "Couldn't find Glide64.ini");1035return M64ERR_FILES;1036}1037}10381039EXPORT m64p_error CALL PluginShutdown(void)1040{1041return M64ERR_SUCCESS;1042}10431044EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)1045{1046/* set version info */1047if (PluginType != NULL)1048*PluginType = M64PLUGIN_GFX;10491050if (PluginVersion != NULL)1051*PluginVersion = PLUGIN_VERSION;10521053if (APIVersion != NULL)1054*APIVersion = VIDEO_PLUGIN_API_VERSION;10551056if (PluginNamePtr != NULL)1057*PluginNamePtr = PLUGIN_NAME;10581059if (Capabilities != NULL)1060{1061*Capabilities = 0;1062}10631064return M64ERR_SUCCESS;1065}10661067/******************************************************************1068Function: CaptureScreen1069Purpose: This function dumps the current frame to a file1070input: pointer to the directory to save the file to1071output: none1072*******************************************************************/1073EXPORT void CALL CaptureScreen ( char * Directory )1074{1075capture_screen = 1;1076strcpy (capture_path, Directory);1077}10781079/******************************************************************1080Function: ChangeWindow1081Purpose: to change the window between fullscreen and window1082mode. If the window was in fullscreen this should1083change the screen to window mode and vice vesa.1084input: none1085output: none1086*******************************************************************/1087EXPORT void CALL ChangeWindow (void)1088{1089LOG ("ChangeWindow()\n");1090//TODO: do this better1091/*1092if (evoodoo)1093{1094if (!ev_fullscreen)1095{1096to_fullscreen = TRUE;1097GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =1098(GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");1099if (grWrapperFullScreenResolutionExt != NULL)1100{1101settings.res_data_org = settings.res_data;1102settings.res_data = grWrapperFullScreenResolutionExt();1103settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];1104settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];1105}1106}1107else1108{1109ReleaseGfx ();1110GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =1111(GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");1112if (grWrapperFullScreenResolutionExt != NULL)1113{1114settings.res_data = settings.res_data_org;1115settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];1116settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];1117}1118InitGfx(TRUE);1119}1120}1121else1122{1123// Go to fullscreen at next dlist1124// This is for compatibility with 1964, which reloads the plugin1125// when switching to fullscreen1126if (!fullscreen)1127{1128to_fullscreen = TRUE;1129}1130else1131{1132ReleaseGfx ();1133}1134}1135*/1136}11371138/******************************************************************1139Function: CloseDLL1140Purpose: This function is called when the emulator is closing1141down allowing the dll to de-initialise.1142input: none1143output: none1144*******************************************************************/1145EXPORT void CALL CloseDLL (void)1146{1147LOG ("CloseDLL ()\n");11481149// re-set the old window proc1150#ifdef WINPROC_OVERRIDE1151SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);1152#endif11531154#ifdef ALTTAB_FIX1155if (hhkLowLevelKybd)1156{1157UnhookWindowsHookEx(hhkLowLevelKybd);1158hhkLowLevelKybd = 0;1159}1160#endif11611162//CLOSELOG ();11631164if (fullscreen)1165ReleaseGfx ();1166ZLUT_release();1167ClearCache ();1168}11691170#if 01171/******************************************************************1172Function: DllAbout1173Purpose: This function is optional function that is provided1174to give further information about the DLL.1175input: a handle to the window that calls this function1176output: none1177*******************************************************************/1178EXPORT void CALL DllAbout ( HWND hParent )1179{1180messagebox("Glide64 v"G64_VERSION, MB_OK,1181"Glide64 "G64_VERSION"\nRelease: " RELTIME "\n"1182"by GuentherB, Richard42, Gonetz, Dave2001, Gugaman, and others\n\n"1183"Beta testers: Raziel64, Federelli, Flash\n\n"1184"Special thanks to:\n"1185"Niki, FiRES, Icepir8, Rice, ZeZu, Azimer, Hacktarux, Cyberman, LoneRaven, Falcon4ever,\n"1186"GokuSS4, _Demo_, Ogy, Quvack, Scorpiove, CpUMasteR, Doom, Lemmy, CyRUS64,\n"1187"McLeod, Linker, StrmnNrmn, Tekken, ExtendedPlay, Kool Smoky\n"1188"everyone at EmuXHaven, all my testers, anyone I've forgotten, and anyone else on\n"1189"the Emutalk message board who helped or brought encouragement\n\n"1190"Thanks to EmuXHaven for hosting my site:\nhttp://glide64.emuxhaven.net/\n\n"1191"Official development channel: #Glide64 on EFnet\nNO ROM REQUESTS / NO BETA REQUESTS");1192}1193#endif11941195/******************************************************************1196Function: DllTest1197Purpose: This function is optional function that is provided1198to allow the user to test the dll1199input: a handle to the window that calls this function1200output: none1201*******************************************************************/1202EXPORT void CALL DllTest ( HWND hParent )1203{1204}12051206/******************************************************************1207Function: DrawScreen1208Purpose: This function is called when the emulator receives a1209WM_PAINT message. This allows the gfx to fit in when1210it is being used in the desktop.1211input: none1212output: none1213*******************************************************************/1214EXPORT void CALL DrawScreen (void)1215{1216LOG ("DrawScreen ()\n");1217}12181219/******************************************************************1220Function: GetDllInfo1221Purpose: This function allows the emulator to gather information1222about the dll by filling in the PluginInfo structure.1223input: a pointer to a PLUGIN_INFO stucture that needs to be1224filled by the function. (see def above)1225output: none1226*******************************************************************/1227EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )1228{1229PluginInfo->Version = 0x0103; // Set to 0x01031230PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX1231sprintf (PluginInfo->Name, "Glide64 "G64_VERSION); // Name of the DLL12321233// If DLL supports memory these memory options then set them to TRUE or FALSE1234// if it does not support it1235PluginInfo->NormalMemory = TRUE; // a normal BYTE array1236PluginInfo->MemoryBswaped = TRUE; // a normal BYTE array where the memory has been pre1237// bswap on a dword (32 bits) boundry1238}12391240#ifndef WIN321241BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)1242{1243struct timeval tv;12441245/* generic routine */1246gettimeofday( &tv, NULL );1247counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;1248return TRUE;1249}12501251BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)1252{1253frequency->s.LowPart= 1000000;1254frequency->s.HighPart= 0;1255return TRUE;1256}1257#endif12581259/******************************************************************1260Function: InitiateGFX1261Purpose: This function is called when the DLL is started to give1262information from the emulator that the n64 graphics1263uses. This is not called from the emulation thread.1264Input: Gfx_Info is passed to this function which is defined1265above.1266Output: TRUE on success1267FALSE on failure to initialise12681269** note on interrupts **:1270To generate an interrupt set the appropriate bit in MI_INTR_REG1271and then call the function CheckInterrupts to tell the emulator1272that there is a waiting interrupt.1273*******************************************************************/12741275EXPORT BOOL CALL InitiateGFX (GFX_INFO Gfx_Info)1276{1277LOG ("InitiateGFX (*)\n");1278// Do *NOT* put this in rdp_reset or it could be set after the screen is initialized1279num_tmu = 2;12801281// Assume scale of 1 for debug purposes1282rdp.scale_x = 1.0f;1283rdp.scale_y = 1.0f;12841285memset (&settings, 0, sizeof(SETTINGS));1286ReadSettings ();12871288#ifdef FPS1289QueryPerformanceFrequency (&perf_freq);1290QueryPerformanceCounter (&fps_last);1291#endif12921293debug_init (); // Initialize debugger12941295gfx = Gfx_Info;1296/*1297char name[21];1298// get the name of the ROM1299for (int i=0; i<20; i++)1300name[i] = gfx.HEADER[(32+i)^3];1301name[20] = 0;13021303// remove all trailing spaces1304while (name[strlen(name)-1] == ' ')1305name[strlen(name)-1] = 0;13061307ReadSpecialSettings (name);1308*/1309#ifdef WINPROC_OVERRIDE1310if (!oldWndProc)1311{1312myWndProc = (WNDPROC)WndProc;1313oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)myWndProc);1314}1315#endif13161317util_init ();1318math_init ();1319TexCacheInit ();1320CRC_BuildTable();1321CountCombine();1322if (settings.fb_depth_render)1323ZLUT_init();13241325return TRUE;1326}13271328/******************************************************************1329Function: MoveScreen1330Purpose: This function is called in response to the emulator1331receiving a WM_MOVE passing the xpos and ypos passed1332from that message.1333input: xpos - the x-coordinate of the upper-left corner of the1334client area of the window.1335ypos - y-coordinate of the upper-left corner of the1336client area of the window.1337output: none1338*******************************************************************/1339EXPORT void CALL MoveScreen (int xpos, int ypos)1340{1341LOG ("MoveScreen");1342}13431344/******************************************************************1345Function: ProcessRDPList1346Purpose: This function is called when there is a Dlist to be1347processed. (Low level GFX list)1348input: none1349output: none1350*******************************************************************/1351#if 01352EXPORT void CALL ProcessRDPList(void)1353{1354if (settings.KI)1355{1356*gfx.MI_INTR_REG |= 0x20;1357gfx.CheckInterrupts();1358}1359LOG ("ProcessRDPList ()\n");1360printf("ProcessRPDList %x %x %x\n",1361*gfx.DPC_START_REG,1362*gfx.DPC_END_REG,1363*gfx.DPC_CURRENT_REG);1364//*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;13651366//*gfx.DPC_START_REG = *gfx.DPC_END_REG;1367*gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;1368}1369#endif13701371/******************************************************************1372Function: ResizeVideoOutput1373Purpose: This function is called to force us to resize our output OpenGL window.1374This is currently unsupported, and should never be called because we do1375not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.1376input: new width and height1377output: none1378*******************************************************************/1379EXPORT void CALL ResizeVideoOutput(int Width, int Height)1380{1381}13821383/******************************************************************1384Function: RomClosed1385Purpose: This function is called when a rom is closed.1386input: none1387output: none1388*******************************************************************/1389EXPORT void CALL RomClosed (void)1390{1391LOG ("RomClosed ()\n");13921393CLOSE_RDP_LOG ();1394CLOSE_RDP_E_LOG ();1395rdp.window_changed = TRUE;1396romopen = FALSE;1397if (fullscreen && evoodoo)1398ReleaseGfx ();1399CoreVideo_Quit();1400}14011402BOOL no_dlist = TRUE;14031404/******************************************************************1405Function: RomOpen1406Purpose: This function is called when a rom is open. (from the1407emulation thread)1408input: none1409output: none1410*******************************************************************/1411EXPORT int CALL RomOpen (void)1412{1413LOG ("RomOpen ()\n");1414if (CoreVideo_Init() != M64ERR_SUCCESS)1415{1416WriteLog(M64MSG_ERROR, "Could not initialize video!");1417return false;1418}14191420no_dlist = TRUE;1421romopen = TRUE;1422ucode_error_report = TRUE; // allowed to report ucode errors14231424// Get the country code & translate to NTSC(0) or PAL(1)1425WORD code = ((WORD*)gfx.HEADER)[0x1F^1];14261427if (code == 0x4400) region = 1; // Germany (PAL)1428if (code == 0x4500) region = 0; // USA (NTSC)1429if (code == 0x4A00) region = 0; // Japan (NTSC)1430if (code == 0x5000) region = 1; // Europe (PAL)1431if (code == 0x5500) region = 0; // Australia (NTSC)14321433char name[21] = "DEFAULT";1434ReadSpecialSettings (name);14351436// get the name of the ROM1437for (int i=0; i<20; i++)1438name[i] = gfx.HEADER[(32+i)^3];1439name[20] = 0;14401441// remove all trailing spaces1442while (name[strlen(name)-1] == ' ')1443name[strlen(name)-1] = 0;14441445ReadSpecialSettings (name);144614471448WriteLog(M64MSG_INFO, "fb_clear %d fb_smart %d\n", settings.fb_depth_clear, settings.fb_smart);144914501451rdp_reset ();1452ClearCache ();14531454OPEN_RDP_LOG ();1455OPEN_RDP_E_LOG ();14561457// ** EVOODOO EXTENSIONS **1458if (!fullscreen)1459{1460grGlideInit ();1461grSstSelect (0);1462}1463const char *extensions = grGetString (GR_EXTENSION);1464WriteLog(M64MSG_INFO, "extensions '%s'\n", extensions);1465if (!fullscreen)1466{1467grGlideShutdown ();14681469if (strstr (extensions, "EVOODOO"))1470evoodoo = 1;1471else1472evoodoo = 0;14731474if (evoodoo)1475InitGfx (TRUE);1476}14771478if (strstr (extensions, "ROMNAME"))1479{1480void (__stdcall *grSetRomName)(char*);1481grSetRomName = (void (__stdcall *)(char*))grGetProcAddress ("grSetRomName");1482grSetRomName (name);1483}1484// **1485return true;1486}14871488/******************************************************************1489Function: ShowCFB1490Purpose: Useally once Dlists are started being displayed, cfb is1491ignored. This function tells the dll to start displaying1492them again.1493input: none1494output: none1495*******************************************************************/1496EXPORT void CALL ShowCFB (void)1497{1498no_dlist = TRUE;1499LOG ("ShowCFB ()\n");1500}15011502EXPORT void CALL SetRenderingCallback(void (*callback)(int))1503{1504renderCallback = callback;1505}15061507/******************************************************************1508Function: UpdateScreen1509Purpose: This function is called in response to a vsync of the1510screen were the VI bit in MI_INTR_REG has already been1511set1512input: none1513output: none1514*******************************************************************/1515DWORD update_screen_count = 0;1516EXPORT void CALL UpdateScreen (void)1517{1518#ifdef LOG_KEY1519if (GetAsyncKeyState (VK_SPACE) & 0x0001)1520{1521LOG ("KEY!!!\n");1522}1523#endif1524char out_buf[512];1525sprintf (out_buf, "UpdateScreen (). distance: %d\n", (int)(*gfx.VI_ORIGIN_REG) - (int)((*gfx.VI_WIDTH_REG) << 2));1526LOG (out_buf);1527// LOG ("UpdateScreen ()\n");15281529DWORD width = (*gfx.VI_WIDTH_REG) << 1;1530if (fullscreen && (*gfx.VI_ORIGIN_REG > width))1531update_screen_count++;15321533// vertical interrupt has occured, increment counter1534vi_count ++;15351536#ifdef FPS1537// Check frames per second1538LARGE_INTEGER difference;1539QueryPerformanceCounter (&fps_next);1540difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart;1541float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart);1542if (diff_secs > 0.5f)1543{1544fps = (float)fps_count / diff_secs;1545vi = (float)vi_count / diff_secs;1546ntsc_percent = vi / 0.6f;1547pal_percent = vi / 0.5f;1548fps_last = fps_next;1549fps_count = 0;1550vi_count = 0;1551}1552#endif1553//*1554DWORD limit = settings.lego ? 15 : 50;1555if (settings.cpu_write_hack && (update_screen_count > limit) && (rdp.last_bg == 0))1556{1557RDP("DirectCPUWrite hack!\n");1558update_screen_count = 0;1559no_dlist = TRUE;1560ClearCache ();1561UpdateScreen();1562return;1563}1564//*/1565//*1566if( no_dlist )1567{1568if( *gfx.VI_ORIGIN_REG > width )1569{1570ChangeSize ();1571RDP("ChangeSize done\n");1572DrawFrameBuffer();1573RDP("DrawFrameBuffer done\n");1574rdp.updatescreen = 1;1575newSwapBuffers ();1576}1577return;1578}1579//*/1580if (settings.swapmode == 0)1581{1582newSwapBuffers ();1583}1584}15851586/******************************************************************1587Function: ViStatusChanged1588Purpose: This function is called to notify the dll that the1589ViStatus registers value has been changed.1590input: none1591output: none1592*******************************************************************/1593EXPORT void CALL ViStatusChanged (void)1594{1595}15961597/******************************************************************1598Function: ViWidthChanged1599Purpose: This function is called to notify the dll that the1600ViWidth registers value has been changed.1601input: none1602output: none1603*******************************************************************/1604EXPORT void CALL ViWidthChanged (void)1605{1606}16071608#ifdef __cplusplus1609}1610#endif16111612161316141615void drawViRegBG();1616void drawNoFullscreenMessage();16171618void DrawFrameBuffer ()1619{1620if (!fullscreen)1621{1622drawNoFullscreenMessage();1623}1624if (to_fullscreen)1625{1626to_fullscreen = FALSE;16271628if (!InitGfx (FALSE))1629{1630LOG ("FAILED!!!\n");1631return;1632}1633fullscreen = TRUE;1634}16351636if (fullscreen)1637{1638grDepthMask (FXTRUE);1639grColorMask (FXTRUE, FXTRUE);1640grBufferClear (0, 0, 0xFFFF);1641drawViRegBG();1642}1643}16441645DWORD curframe = 0;1646void newSwapBuffers()1647{1648if (rdp.updatescreen)1649{1650rdp.updatescreen = 0;16511652RDP ("swapped\n");16531654// Allow access to the whole screen1655if (fullscreen)1656{1657grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);1658grDepthBufferFunction (GR_CMP_ALWAYS);1659grDepthMask (FXFALSE);16601661grCullMode (GR_CULL_DISABLE);16621663if ((settings.show_fps & 0xF) || settings.clock)1664set_message_combiner ();1665#ifdef FPS1666float y = (float)settings.res_y;1667if (settings.show_fps & 0x0F)1668{1669if (settings.show_fps & 4)1670{1671if (region) // PAL1672output (0, y, 0, "%d%% ", (int)pal_percent);1673else1674output (0, y, 0, "%d%% ", (int)ntsc_percent);1675y -= 16;1676}1677if (settings.show_fps & 2)1678{1679output (0, y, 0, "VI/s: %.02f ", vi);1680y -= 16;1681}1682if (settings.show_fps & 1)1683output (0, y, 0, "FPS: %.02f ", fps);1684}1685#endif16861687if (settings.clock)1688{1689if (settings.clock_24_hr)1690{1691time_t ltime;1692time (<ime);1693tm *cur_time = localtime (<ime);16941695sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);1696}1697else1698{1699char ampm[] = "AM";1700time_t ltime;17011702time (<ime);1703tm *cur_time = localtime (<ime);17041705if (cur_time->tm_hour >= 12)1706{1707strcpy (ampm, "PM");1708if (cur_time->tm_hour != 12)1709cur_time->tm_hour -= 12;1710}1711if (cur_time->tm_hour == 0)1712cur_time->tm_hour = 12;17131714if (cur_time->tm_hour >= 10)1715sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);1716else1717sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);1718}1719output ((float)(settings.res_x - 68), y, 0, out_buf, 0);1720}1721}17221723// Capture the screen if debug capture is set1724if (debug.capture)1725{1726// Allocate the screen1727debug.screen = new BYTE [(settings.res_x*settings.res_y) << 1];17281729// Lock the backbuffer (already rendered)1730GrLfbInfo_t info;1731info.size = sizeof(GrLfbInfo_t);1732while (!grLfbLock (GR_LFB_READ_ONLY,1733GR_BUFFER_BACKBUFFER,1734GR_LFBWRITEMODE_565,1735GR_ORIGIN_UPPER_LEFT,1736FXFALSE,1737&info));17381739DWORD offset_src=0/*(settings.scr_res_y-settings.res_y)*info.strideInBytes*/, offset_dst=0;17401741// Copy the screen1742for (DWORD y=0; y<settings.res_y; y++)1743{1744memcpy (debug.screen + offset_dst, (BYTE*)info.lfbPtr + offset_src, settings.res_x << 1);1745offset_dst += settings.res_x << 1;1746offset_src += info.strideInBytes;1747}17481749// Unlock the backbuffer1750grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);1751}17521753if (fullscreen)1754{1755LOG ("BUFFER SWAPPED\n");1756grBufferSwap (settings.vsync);1757fps_count ++;1758}17591760if (fullscreen && (debugging || settings.wireframe || settings.buff_clear))1761{1762if (settings.RE2 && settings.fb_depth_render)1763grDepthMask (FXFALSE);1764else1765grDepthMask (FXTRUE);1766grBufferClear (0, 0, 0xFFFF);1767}17681769frame_count ++;1770}1771}177217731774#ifdef WINPROC_OVERRIDE1775LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)1776{1777switch (msg)1778{1779case WM_ACTIVATE:1780rdp.window_changed = TRUE;1781break;17821783/* case WM_DESTROY:1784SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);1785break;*/1786}17871788return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);1789}1790#endif17911792BOOL k_ctl=0, k_alt=0, k_del=0;17931794#ifdef ALTTAB_FIX1795LRESULT CALLBACK LowLevelKeyboardProc(int nCode,1796WPARAM wParam, LPARAM lParam) {1797if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);17981799BOOL TabKey = FALSE;18001801PKBDLLHOOKSTRUCT p;18021803if (nCode == HC_ACTION)1804{1805switch (wParam) {1806case WM_KEYUP: case WM_SYSKEYUP:1807p = (PKBDLLHOOKSTRUCT) lParam;1808if (p->vkCode == 162) k_ctl = 0;1809if (p->vkCode == 164) k_alt = 0;1810if (p->vkCode == 46) k_del = 0;1811goto do_it;18121813case WM_KEYDOWN: case WM_SYSKEYDOWN:1814p = (PKBDLLHOOKSTRUCT) lParam;1815if (p->vkCode == 162) k_ctl = 1;1816if (p->vkCode == 164) k_alt = 1;1817if (p->vkCode == 46) k_del = 1;1818goto do_it;18191820do_it:1821TabKey =1822((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||1823((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||1824((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) ||1825(k_ctl && k_alt && k_del);18261827break;1828}1829}18301831if (TabKey)1832{1833k_ctl = 0;1834k_alt = 0;1835k_del = 0;1836ReleaseGfx ();1837}18381839return CallNextHookEx(NULL, nCode, wParam, lParam);1840}1841#endif1842184318441845