├── .gitignore ├── 3rdparty ├── config.h ├── confuse.c ├── confuse.h ├── glew.c └── lexer.c ├── LICENSE ├── README.md ├── cfg.c ├── cfg.h ├── common.c ├── common.h ├── common_imports.h ├── compile_cfg.h ├── crashdump.c ├── crashdump.h ├── ctx.c ├── ctx.h ├── externals_102_de.h ├── externals_102_fr.h ├── externals_102_sp.h ├── externals_102_us.h ├── fake_dd.c ├── fake_dd.h ├── ff7.h ├── ff7 ├── battle.c ├── defs.h ├── field.c ├── file.c ├── graphics.c ├── loaders.c └── misc.c ├── ff7_data.h ├── ff7_opengl.c ├── ff7music ├── music.c └── types.h ├── ff8.h ├── ff8_data.h ├── ff8_opengl.c ├── ffmpeg_movies ├── ffmpeg_glue.c ├── ffmpeg_movies.c └── types.h ├── gl.h ├── gl ├── deferred.c ├── gl.c ├── shader.c ├── special_case.c └── texture.c ├── globals.h ├── log.c ├── log.h ├── macro.h ├── matrix.c ├── matrix.h ├── movies.c ├── movies.h ├── music.c ├── music.h ├── patch.c ├── patch.h ├── png.c ├── png.h ├── saveload.c ├── saveload.h ├── types.h └── vgmstream_music ├── music.c └── types.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /3rdparty/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Handcrafted for Microsoft Visual Studio. */ 2 | 3 | /* Define to 1 if translation of program messages to the user's native 4 | language is requested. */ 5 | /*#undef ENABLE_NLS*/ 6 | 7 | /* Define if the GNU dcgettext() function is already present or preinstalled. 8 | */ 9 | /*#undef HAVE_DCGETTEXT*/ 10 | 11 | /* Define to 1 if you have the header file. */ 12 | /*#undef HAVE_DLFCN_H*/ 13 | 14 | /* Define if the GNU gettext() function is already present or preinstalled. */ 15 | /*#undef HAVE_GETTEXT*/ 16 | 17 | /* Define if you have the iconv() function. */ 18 | /*#undef HAVE_ICONV*/ 19 | 20 | /* Define to 1 if you have the header file. */ 21 | /*#undef HAVE_INTTYPES_H*/ 22 | 23 | /* Define to 1 if you have the header file. */ 24 | #define HAVE_MEMORY_H 1 25 | 26 | /* Define to 1 if you have the header file. */ 27 | #define HAVE_STDINT_H 1 28 | 29 | /* Define to 1 if you have the header file. */ 30 | #define HAVE_STDLIB_H 1 31 | 32 | /* Define to 1 if you have the `strcasecmp' function. */ 33 | /*#define HAVE_STRCASECMP 1*/ 34 | 35 | /* Define to 1 if you have the `strdup' function. */ 36 | /*#define HAVE_STRDUP 1*/ 37 | 38 | /* Define to 1 if you have the `_strdup' function. */ 39 | #define HAVE__STRDUP 1 40 | 41 | /* Define to 1 if you have the header file. */ 42 | /*#undef HAVE_STRINGS_H*/ 43 | 44 | /* Define to 1 if you have the header file. */ 45 | #define HAVE_STRING_H 1 46 | 47 | /* Define to 1 if you have the header file. */ 48 | #undef HAVE_SYS_STAT_H 49 | 50 | /* Define to 1 if you have the header file. */ 51 | #define HAVE_SYS_TYPES_H 1 52 | 53 | /* Define to 1 if you have the header file. */ 54 | /*#undef HAVE_UNISTD_H*/ 55 | 56 | /* Name of package */ 57 | #define PACKAGE "confuse" 58 | 59 | /* Define to the address where bug reports for this package should be sent. */ 60 | #define PACKAGE_BUGREPORT "confuse-devel@nongnu.org" 61 | 62 | /* Define to the full name of this package. */ 63 | #define PACKAGE_NAME "libConfuse" 64 | 65 | /* Define to the full name and version of this package. */ 66 | #define PACKAGE_STRING "libConfuse 2.5" 67 | 68 | /* Define to the one symbol short name of this package. */ 69 | #define PACKAGE_TARNAME "confuse" 70 | 71 | /* Define to the version of this package. */ 72 | #define PACKAGE_VERSION "2.5" 73 | 74 | /* Define to 1 if you have the ANSI C header files. */ 75 | #define STDC_HEADERS 1 76 | 77 | /* Version number of package */ 78 | #define VERSION "2.5" 79 | 80 | /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a 81 | `char[]'. */ 82 | /*#undef YYTEXT_POINTER*/ 83 | 84 | /* Define to empty if `const' does not conform to ANSI C. */ 85 | /*#undef const*/ 86 | 87 | /* Define to 1 if you have the strndup function */ 88 | /*#undef HAVE_STRNDUP */ 89 | 90 | /* Define if you have _fileno instead of fileno */ 91 | #define HAVE__FILENO 1 92 | 93 | /* Define if you have _isatty but not isatty */ 94 | #define HAVE__ISATTY 1 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ff7_opengl 2 | Complete OpenGL replacement of the Direct3D renderer used in the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 3 | -------------------------------------------------------------------------------- /cfg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * cfg.c - configuration file parser based on libconfuse 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "types.h" 27 | #include "3rdparty/confuse.h" 28 | #include "log.h" 29 | #include "globals.h" 30 | #include "compile_cfg.h" 31 | 32 | // configuration variables with their default values 33 | char *mod_path; 34 | char *movie_plugin; 35 | char *music_plugin; 36 | bool save_textures = false; 37 | char *traced_texture; 38 | char *vert_source; 39 | char *frag_source; 40 | char *yuv_source; 41 | char *post_source; 42 | bool enable_postprocessing = false; 43 | bool trace_all = false; 44 | bool trace_movies = false; 45 | bool trace_fake_dx = false; 46 | bool trace_direct = false; 47 | bool trace_files = false; 48 | bool trace_loaders = false; 49 | bool trace_lights = false; 50 | bool vertex_log = false; 51 | bool show_fps = false; 52 | bool show_stats = false; 53 | uint window_size_x = 0; 54 | uint window_size_y = 0; 55 | int window_pos_x = 0; 56 | int window_pos_y = 0; 57 | bool preserve_aspect = true; 58 | bool fullscreen = true; 59 | uint refresh_rate = 0; 60 | bool prevent_rounding_errors = true; 61 | uint internal_size_x = 0; 62 | uint internal_size_y = 0; 63 | bool enable_vsync = true; 64 | uint field_framerate = 30; 65 | uint battle_framerate = 15; 66 | uint worldmap_framerate = 30; 67 | uint menu_framerate = 30; 68 | uint chocobo_framerate = 30; 69 | uint condor_framerate = 30; 70 | uint submarine_framerate = 30; 71 | uint gameover_framerate = 30; 72 | uint credits_framerate = 30; 73 | uint snowboard_framerate = 60; 74 | uint highway_framerate = 30; 75 | uint coaster_framerate = 60; 76 | uint battleswirl_framerate = 30; 77 | bool use_new_timer = true; 78 | bool linear_filter = false; 79 | bool transparent_dialogs = false; 80 | bool mdef_fix = true; 81 | bool fancy_transparency = true; 82 | bool compress_textures = false; 83 | uint texture_cache_size = 256; 84 | bool use_pbo = true; 85 | bool use_mipmaps = true; 86 | bool skip_frames = false; 87 | bool more_ff7_debug = false; 88 | bool show_applog = true; 89 | bool direct_mode = false; 90 | bool show_missing_textures = false; 91 | bool ff7_popup = false; 92 | bool info_popup = false; 93 | char *load_library; 94 | bool opengl_debug = false; 95 | bool movie_sync_debug = false; 96 | 97 | cfg_opt_t opts[] = { 98 | CFG_SIMPLE_STR("mod_path", &mod_path), 99 | CFG_SIMPLE_STR("movie_plugin", &movie_plugin), 100 | CFG_SIMPLE_STR("music_plugin", &music_plugin), 101 | CFG_SIMPLE_BOOL("save_textures", &save_textures), 102 | CFG_SIMPLE_STR("traced_texture", &traced_texture), 103 | CFG_SIMPLE_STR("vert_source", &vert_source), 104 | CFG_SIMPLE_STR("frag_source", &frag_source), 105 | CFG_SIMPLE_STR("yuv_source", &yuv_source), 106 | CFG_SIMPLE_STR("post_source", &post_source), 107 | CFG_SIMPLE_BOOL("enable_postprocessing", &enable_postprocessing), 108 | CFG_SIMPLE_BOOL("trace_all", &trace_all), 109 | CFG_SIMPLE_BOOL("trace_movies", &trace_movies), 110 | CFG_SIMPLE_BOOL("trace_fake_dx", &trace_fake_dx), 111 | CFG_SIMPLE_BOOL("trace_direct", &trace_direct), 112 | CFG_SIMPLE_BOOL("trace_files", &trace_files), 113 | CFG_SIMPLE_BOOL("trace_loaders", &trace_loaders), 114 | CFG_SIMPLE_BOOL("trace_lights", &trace_lights), 115 | CFG_SIMPLE_BOOL("vertex_log", &vertex_log), 116 | CFG_SIMPLE_BOOL("show_fps", &show_fps), 117 | CFG_SIMPLE_BOOL("show_stats", &show_stats), 118 | CFG_SIMPLE_INT("window_size_x", &window_size_x), 119 | CFG_SIMPLE_INT("window_size_y", &window_size_y), 120 | CFG_SIMPLE_INT("window_pos_x", &window_pos_x), 121 | CFG_SIMPLE_INT("window_pos_y", &window_pos_y), 122 | CFG_SIMPLE_BOOL("preserve_aspect", &preserve_aspect), 123 | CFG_SIMPLE_BOOL("fullscreen", &fullscreen), 124 | CFG_SIMPLE_INT("refresh_rate", &refresh_rate), 125 | CFG_SIMPLE_BOOL("prevent_rounding_errors", &prevent_rounding_errors), 126 | CFG_SIMPLE_INT("internal_size_x", &internal_size_x), 127 | CFG_SIMPLE_INT("internal_size_y", &internal_size_y), 128 | CFG_SIMPLE_BOOL("enable_vsync", &enable_vsync), 129 | CFG_SIMPLE_INT("field_framerate", &field_framerate), 130 | CFG_SIMPLE_INT("battle_framerate", &battle_framerate), 131 | CFG_SIMPLE_INT("worldmap_framerate", &worldmap_framerate), 132 | CFG_SIMPLE_INT("menu_framerate", &menu_framerate), 133 | CFG_SIMPLE_INT("chocobo_framerate", &chocobo_framerate), 134 | CFG_SIMPLE_INT("condor_framerate", &condor_framerate), 135 | CFG_SIMPLE_INT("submarine_framerate", &submarine_framerate), 136 | CFG_SIMPLE_INT("gameover_framerate", &gameover_framerate), 137 | CFG_SIMPLE_INT("credits_framerate", &credits_framerate), 138 | CFG_SIMPLE_INT("snowboard_framerate", &snowboard_framerate), 139 | CFG_SIMPLE_INT("highway_framerate", &highway_framerate), 140 | CFG_SIMPLE_INT("coaster_framerate", &coaster_framerate), 141 | CFG_SIMPLE_INT("battleswirl_framerate", &battleswirl_framerate), 142 | CFG_SIMPLE_BOOL("use_new_timer", &use_new_timer), 143 | CFG_SIMPLE_BOOL("linear_filter", &linear_filter), 144 | CFG_SIMPLE_BOOL("transparent_dialogs", &transparent_dialogs), 145 | CFG_SIMPLE_BOOL("mdef_fix", &mdef_fix), 146 | CFG_SIMPLE_BOOL("fancy_transparency", &fancy_transparency), 147 | CFG_SIMPLE_BOOL("compress_textures", &compress_textures), 148 | CFG_SIMPLE_INT("texture_cache_size", &texture_cache_size), 149 | CFG_SIMPLE_BOOL("use_pbo", &use_pbo), 150 | CFG_SIMPLE_BOOL("use_mipmaps", &use_mipmaps), 151 | CFG_SIMPLE_BOOL("skip_frames", &skip_frames), 152 | CFG_SIMPLE_BOOL("more_ff7_debug", &more_ff7_debug), 153 | CFG_SIMPLE_BOOL("show_applog", &show_applog), 154 | CFG_SIMPLE_BOOL("direct_mode", &direct_mode), 155 | CFG_SIMPLE_BOOL("show_missing_textures", &show_missing_textures), 156 | CFG_SIMPLE_BOOL("ff7_popup", &ff7_popup), 157 | CFG_SIMPLE_BOOL("info_popup", &info_popup), 158 | CFG_SIMPLE_STR("load_library", &load_library), 159 | CFG_SIMPLE_BOOL("opengl_debug", &opengl_debug), 160 | CFG_SIMPLE_BOOL("movie_sync_debug", &movie_sync_debug), 161 | 162 | CFG_END() 163 | }; 164 | 165 | void error_callback(cfg_t *cfg, const char *fmt, va_list ap) 166 | { 167 | char config_error_string[4096]; 168 | char display_string[4096]; 169 | 170 | vsnprintf(config_error_string, sizeof(config_error_string), fmt, ap); 171 | 172 | error("parse error in config file\n"); 173 | error("%s\n", config_error_string); 174 | sprintf(display_string, "You have an error in your config file, some options may not have been parsed.\n(%s)", config_error_string); 175 | MessageBoxA(hwnd, display_string, "Warning", 0); 176 | } 177 | 178 | void read_cfg() 179 | { 180 | char filename[BASEDIR_LENGTH + 1024]; 181 | 182 | cfg_t *cfg; 183 | 184 | mod_path = strdup(""); 185 | if(!ff8) movie_plugin = strdup("plugins/ffmpeg_movies.fgp"); 186 | else movie_plugin = strdup(""); 187 | music_plugin = strdup(""); 188 | vert_source = strdup("shaders/main.vert"); 189 | frag_source = strdup("shaders/main.frag"); 190 | yuv_source = strdup("shaders/yuv.frag"); 191 | post_source = strdup(""); 192 | 193 | traced_texture = strdup(""); 194 | 195 | load_library = strdup(""); 196 | 197 | if(!ff8) _snprintf(filename, sizeof(filename), "%s/ff7_opengl.cfg", basedir); 198 | else _snprintf(filename, sizeof(filename), "%s/ff8_opengl.cfg", basedir); 199 | 200 | cfg = cfg_init(opts, 0); 201 | 202 | cfg_set_error_function(cfg, error_callback); 203 | 204 | cfg_parse(cfg, filename); 205 | 206 | cfg_free(cfg); 207 | 208 | #ifdef SINGLE_STEP 209 | window_size_x = 0; 210 | window_size_y = 0; 211 | fullscreen = false; 212 | #endif 213 | } 214 | -------------------------------------------------------------------------------- /cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * cfg.h - configuration variable definitions 21 | */ 22 | 23 | #ifndef _CFG_H_ 24 | #define _CFG_H_ 25 | 26 | #include "types.h" 27 | 28 | extern char *mod_path; 29 | extern char *movie_plugin; 30 | extern char *music_plugin; 31 | extern bool save_textures; 32 | extern char *traced_texture; 33 | extern char *vert_source; 34 | extern char *frag_source; 35 | extern char *yuv_source; 36 | extern char *post_source; 37 | extern bool enable_postprocessing; 38 | extern bool trace_all; 39 | extern bool trace_movies; 40 | extern bool trace_fake_dx; 41 | extern bool trace_direct; 42 | extern bool trace_files; 43 | extern bool trace_loaders; 44 | extern bool trace_lights; 45 | extern bool vertex_log; 46 | extern bool show_fps; 47 | extern bool show_stats; 48 | extern uint window_size_x; 49 | extern uint window_size_y; 50 | extern int window_pos_x; 51 | extern int window_pos_y; 52 | extern bool preserve_aspect; 53 | extern bool fullscreen; 54 | extern uint refresh_rate; 55 | extern bool prevent_rounding_errors; 56 | extern uint internal_size_x; 57 | extern uint internal_size_y; 58 | extern bool enable_vsync; 59 | extern uint field_framerate; 60 | extern uint battle_framerate; 61 | extern uint worldmap_framerate; 62 | extern uint menu_framerate; 63 | extern uint chocobo_framerate; 64 | extern uint condor_framerate; 65 | extern uint submarine_framerate; 66 | extern uint gameover_framerate; 67 | extern uint credits_framerate; 68 | extern uint snowboard_framerate; 69 | extern uint highway_framerate; 70 | extern uint coaster_framerate; 71 | extern uint battleswirl_framerate; 72 | extern bool use_new_timer; 73 | extern bool linear_filter; 74 | extern bool transparent_dialogs; 75 | extern bool mdef_fix; 76 | extern bool fancy_transparency; 77 | extern bool compress_textures; 78 | extern uint texture_cache_size; 79 | extern bool use_pbo; 80 | extern bool use_mipmaps; 81 | extern bool skip_frames; 82 | extern bool more_ff7_debug; 83 | extern bool show_applog; 84 | extern bool direct_mode; 85 | extern bool show_missing_textures; 86 | extern bool ff7_popup; 87 | extern bool info_popup; 88 | extern char *load_library; 89 | extern bool opengl_debug; 90 | extern bool movie_sync_debug; 91 | 92 | void read_cfg(); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * common.h - data structures and functions common to both games 21 | */ 22 | 23 | #ifndef _COMMON_H_ 24 | #define _COMMON_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "types.h" 31 | #include "compile_cfg.h" 32 | #include "matrix.h" 33 | #include "common_imports.h" 34 | 35 | // all known OFFICIAL versions of FF7 & FF8 released for the PC 36 | #define VERSION_FF7_102_US 1 37 | #define VERSION_FF7_102_FR 2 38 | #define VERSION_FF7_102_DE 3 39 | #define VERSION_FF7_102_SP 4 40 | #define VERSION_FF8_12_US 5 41 | #define VERSION_FF8_12_US_NV 6 42 | #define VERSION_FF8_12_FR 7 43 | #define VERSION_FF8_12_FR_NV 8 44 | #define VERSION_FF8_12_DE 9 45 | #define VERSION_FF8_12_DE_NV 10 46 | #define VERSION_FF8_12_SP 11 47 | #define VERSION_FF8_12_SP_NV 12 48 | #define VERSION_FF8_12_IT 13 49 | #define VERSION_FF8_12_IT_NV 14 50 | #define VERSION_FF8_12_US_EIDOS 15 51 | #define VERSION_FF8_12_US_EIDOS_NV 16 52 | #define VERSION_FF8_12_JP 17 53 | 54 | #define NV_VERSION (!(version & 1)) 55 | 56 | // FF8 does not support BLUE text! 57 | enum 58 | { 59 | TEXTCOLOR_GRAY, 60 | TEXTCOLOR_BLUE, 61 | TEXTCOLOR_RED, 62 | TEXTCOLOR_PINK, 63 | TEXTCOLOR_GREEN, 64 | TEXTCOLOR_LIGHT_BLUE, 65 | TEXTCOLOR_YELLOW, 66 | TEXTCOLOR_WHITE, 67 | NUM_TEXTCOLORS 68 | }; 69 | 70 | enum game_modes 71 | { 72 | MODE_FIELD = 0, 73 | MODE_BATTLE, 74 | MODE_WORLDMAP, 75 | MODE_MENU, 76 | MODE_HIGHWAY, 77 | MODE_CHOCOBO, 78 | MODE_SNOWBOARD, 79 | MODE_CONDOR, 80 | MODE_SUBMARINE, 81 | MODE_COASTER, 82 | MODE_CDCHECK, 83 | MODE_EXIT, 84 | MODE_SWIRL, 85 | MODE_GAMEOVER, 86 | MODE_CREDITS, 87 | MODE_INTRO, 88 | MODE_CARDGAME, 89 | MODE_UNKNOWN, 90 | }; 91 | 92 | // popup lifetime in frames 93 | #define POPUP_TTL_MAX 10000 94 | 95 | // dummy TEX version for framebuffer textures 96 | #define FB_TEX_VERSION 100 97 | 98 | struct game_mode 99 | { 100 | uint mode; 101 | char *name; 102 | uint driver_mode; 103 | bool trace; 104 | uint main_loop; 105 | uint framerate; 106 | }; 107 | 108 | gfx_init common_init; 109 | gfx_cleanup common_cleanup; 110 | gfx_lock common_lock; 111 | gfx_unlock common_unlock; 112 | gfx_flip common_flip; 113 | gfx_clear common_clear; 114 | gfx_clear_all common_clear_all; 115 | gfx_setviewport common_setviewport; 116 | gfx_setbg common_setbg; 117 | gfx_prepare_polygon_set common_prepare_polygon_set; 118 | gfx_load_group common_load_group; 119 | gfx_setmatrix common_setmatrix; 120 | gfx_unload_texture common_unload_texture; 121 | gfx_load_texture common_load_texture; 122 | gfx_palette_changed common_palette_changed; 123 | gfx_write_palette common_write_palette; 124 | gfx_blendmode common_blendmode; 125 | gfx_light_polygon_set ff7gl_light_polygon_set; 126 | gfx_field_64 common_field_64; 127 | gfx_setrenderstate common_setrenderstate; 128 | gfx_field_74 common_field_74; 129 | gfx_field_78 common_field_78; 130 | gfx_draw_deferred common_draw_deferred; 131 | gfx_field_80 common_field_80; 132 | gfx_field_84 common_field_84; 133 | gfx_begin_scene common_begin_scene; 134 | gfx_end_scene common_end_scene; 135 | gfx_field_90 common_field_90; 136 | gfx_polysetrenderstate common_setrenderstate_2D; 137 | gfx_draw_vertices common_draw_2D; 138 | gfx_draw_vertices common_draw_paletted2D; 139 | gfx_polysetrenderstate common_setrenderstate_3D; 140 | gfx_draw_vertices common_draw_3D; 141 | gfx_draw_vertices common_draw_paletted3D; 142 | gfx_draw_vertices common_draw_lines; 143 | gfx_field_EC common_field_EC; 144 | 145 | /* 146 | * This structure holds memory addresses and function pointers of the original 147 | * engine used within this program. Not all of them are currently used for both 148 | * games, MIDI functions for example are only used for FF7 but they could 149 | * concievably be used for FF8 aswell. 150 | */ 151 | 152 | struct common_externals 153 | { 154 | word *_mode; 155 | uint dinput_hack1; 156 | gfx_load_group *generic_load_group; 157 | gfx_light_polygon_set *generic_light_polygon_set; 158 | void *(*assert_free)(void *, const char *, uint); 159 | void *(*assert_malloc)(uint, const char *, uint); 160 | void *(*assert_calloc)(uint, uint, const char *, uint); 161 | void **directsound; 162 | struct palette *(*create_palette_for_tex)(uint, struct tex_header *, struct texture_set *); 163 | struct game_obj *(*get_game_object)(); 164 | struct texture_format *(*create_texture_format)(); 165 | void (*add_texture_format)(struct texture_format *, struct game_obj *); 166 | void (*make_pixelformat)(uint, uint, uint, uint, uint, struct texture_format *); 167 | struct texture_set *(*create_texture_set)(); 168 | uint debug_print; 169 | uint debug_print2; 170 | uint prepare_movie; 171 | uint release_movie_objects; 172 | uint start_movie; 173 | uint update_movie_sample; 174 | uint stop_movie; 175 | uint get_movie_frame; 176 | struct tex_header *(*create_tex_header)(); 177 | uint get_time; 178 | uint midi_init; 179 | char *(*get_midi_name)(uint); 180 | uint play_midi; 181 | uint stop_midi; 182 | uint cross_fade_midi; 183 | uint pause_midi; 184 | uint restart_midi; 185 | uint midi_status; 186 | uint set_master_midi_volume; 187 | uint set_midi_volume; 188 | uint set_midi_volume_trans; 189 | uint set_midi_tempo; 190 | uint draw_graphics_object; 191 | char *font_info; 192 | uint build_dialog_window; 193 | uint write_file; 194 | uint close_file; 195 | uint open_file; 196 | uint read_file; 197 | uint __read_file; 198 | uint get_filesize; 199 | uint tell_file; 200 | uint seek_file; 201 | void *(*alloc_read_file)(uint, uint, struct file *); 202 | void *(*alloc_get_file)(struct file_context *, uint *, char *); 203 | void (*destroy_tex)(struct tex_header *); 204 | uint destroy_tex_header; 205 | uint start; 206 | uint winmain; 207 | uint load_tex_file; 208 | }; 209 | 210 | // heap allocation wrappers 211 | // driver_* functions are to be used for data internal to the driver, memory which is never allocated or free'd by the game 212 | // external_* functions must be used for memory which could be allocated or free'd by the game 213 | // see compile_cfg.h for more information on preprocessor defines 214 | #ifndef NO_EXT_HEAP 215 | #define external_free(x) common_externals.assert_free(x, "", 0) 216 | #define external_malloc(x) common_externals.assert_malloc(x, "", 0) 217 | #define external_calloc(x, y) common_externals.assert_calloc(x, y, "", 0) 218 | #else 219 | void ext_free(void *ptr, const char *file, uint line); 220 | void *ext_malloc(uint size, const char *file, uint line); 221 | void *ext_calloc(uint size, uint num, const char *file, uint line); 222 | 223 | #define external_free(x) ext_free(x, "", 0) 224 | #define external_malloc(x) ext_malloc(x, "", 0) 225 | #define external_calloc(x, y) ext_calloc(x, y, "", 0) 226 | #endif 227 | 228 | #ifndef HEAP_DEBUG 229 | #define driver_malloc(x) malloc(x) 230 | #define driver_calloc(x, y) calloc(x, y) 231 | #define driver_free(x) free(x) 232 | #define driver_realloc(x, y) realloc(x, y) 233 | #else 234 | void *driver_malloc(uint size); 235 | void *driver_calloc(uint size, uint num); 236 | void driver_free(void *ptr); 237 | void *driver_realloc(void *ptr, uint size); 238 | #endif 239 | 240 | // profiling routines, see compile_cfg.h 241 | #ifdef PROFILE 242 | #define PROFILE_START() qpc_get_time(&profile_start) 243 | #define PROFILE_END() { qpc_get_time(&profile_end); profile_total += profile_end - profile_start; } 244 | 245 | extern time_t profile_start; 246 | extern time_t profile_end; 247 | extern time_t profile_total; 248 | #endif PROFILE 249 | 250 | struct driver_stats 251 | { 252 | uint texture_count; 253 | uint external_textures; 254 | uint ext_cache_size; 255 | uint texture_reloads; 256 | uint palette_writes; 257 | uint palette_changes; 258 | uint vertex_count; 259 | uint deferred; 260 | time_t timer; 261 | }; 262 | 263 | void qpc_get_time(time_t *dest); 264 | bool init_opengl(); 265 | uint get_version(); 266 | struct game_mode *getmode(); 267 | struct game_mode *getmode_cached(); 268 | struct tex_header *make_framebuffer_tex(uint tex_w, uint tex_h, uint x, uint y, uint w, uint h, bool color_key); 269 | void internal_set_renderstate(uint state, uint option, struct game_obj *game_object); 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /compile_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * compile_cfg.h - compile time configuration options 21 | */ 22 | 23 | #ifndef _COMPILE_CFG_H_ 24 | #define _COMPILE_CFG_H_ 25 | 26 | /* 27 | * RELEASE 28 | * 29 | * Enables compile time checks to make sure no debugging options have been left 30 | * enabled and removes debug output. 31 | */ 32 | //#define RELEASE 33 | 34 | /* 35 | * PRERELEASE 36 | * 37 | * Adds prerelease warning to applog and ingame. Only valid in conjunction with 38 | * RELEASE. 39 | */ 40 | //#define PRERELEASE 41 | 42 | /* 43 | * VERSION 44 | * 45 | * Version string used in applog. 46 | */ 47 | #define VERSION "0.8.2b" 48 | 49 | /* 50 | * SINGLE_STEP 51 | * 52 | * Forces window mode in original resolution and places the renderer into 53 | * single step mode, in this mode double buffering is disabled and the result 54 | * of each render call is immediately flushed to the screen, allowing you 55 | * to set breakpoints in the rendering process and see exactly what has been 56 | * drawn up to that point. 57 | */ 58 | //#define SINGLE_STEP 59 | 60 | /* 61 | * HEAP_DEBUG 62 | * 63 | * Trace and keep count of every allocation made by this program. Number of 64 | * allocations can be seen ingame through the show_stats option. 65 | */ 66 | //#define HEAP_DEBUG 67 | 68 | /* 69 | * NO_EXT_HEAP 70 | * 71 | * Reroutes allocations from the game itself to our heap. Can be used with the 72 | * above option to also trace allocations from the game. The game WILL crash on 73 | * exit when this option is enabled. This is normal. 74 | */ 75 | //#define NO_EXT_HEAP 76 | 77 | /* 78 | * PROFILE 79 | * 80 | * Enables profiling functions and profiling display through the show_stats 81 | * option. A running total of the time spent between PROFILE_START() and 82 | * PROFILE_END() pairs will be displayed ingame. 83 | */ 84 | //#define PROFILE 85 | 86 | 87 | // check for invalid combinations of options 88 | #ifdef RELEASE 89 | #ifdef SINGLE_STEP 90 | #error 91 | #endif 92 | #ifdef HEAP_DEBUG 93 | #error 94 | #endif 95 | #ifdef PROFILE 96 | #error 97 | #endif 98 | #else 99 | #ifdef PRERELEASE 100 | #error 101 | #endif 102 | #endif 103 | 104 | #ifdef PRERELEASE 105 | #define PRERELEASE_WARNING " PRERELEASE DO NOT DISTRIBUTE" 106 | #else 107 | #define PRERELEASE_WARNING "" 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /crashdump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * crashdump.c - crash dump & emergency save functionality 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "globals.h" 28 | #include "types.h" 29 | #include "log.h" 30 | 31 | // FF7 save file checksum, original by dziugo 32 | int ff7_checksum(void* qw) 33 | { 34 | int i = 0, t, d; 35 | long r = 0xFFFF, len = 4336; 36 | long pbit = 0x8000; 37 | char* b = (char*)qw; 38 | 39 | while(len--) 40 | { 41 | t = b[i++]; 42 | r ^= t << 8; 43 | 44 | for(d = 0; d < 8; d++) 45 | { 46 | if(r & pbit) r = (r << 1) ^ 0x1021; 47 | else r <<= 1; 48 | } 49 | 50 | r &= (1 << 16) - 1; 51 | } 52 | 53 | return (r ^ 0xFFFF) & 0xFFFF; 54 | } 55 | 56 | static const char crash_dmp[] = "crash.dmp"; 57 | 58 | static const char save_name[] = "\x25" "MERGENCY" "\x00\x33" "AVE" "\xFF"; 59 | 60 | LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) 61 | { 62 | static bool had_exception = false; 63 | HMODULE dbghelp; 64 | char filename[4096]; 65 | bool save; 66 | 67 | // give up if we crash again inside the exception handler (this function) 68 | if(had_exception) 69 | { 70 | SetUnhandledExceptionFilter(0); 71 | return EXCEPTION_CONTINUE_EXECUTION; 72 | } 73 | 74 | had_exception = true; 75 | 76 | // show cursor in case it was hidden 77 | ShowCursor(true); 78 | 79 | if(!ff8) 80 | { 81 | save = MessageBoxA(0, "Oops! Something very bad happened\nWrote crash.dmp to FF7 install dir.\n" 82 | "Please provide a copy of it along with APP.LOG when reporting this error.\n" 83 | "Write emergency save to save/crash.ff7?", "Error", MB_YESNO) == IDYES; 84 | } 85 | else 86 | { 87 | MessageBoxA(0, "Oops! Something very bad happened\nWrote crash.dmp to FF8 install dir.\n" 88 | "Please provide a copy of it along with APP.LOG when reporting this error.\n", "Error", MB_OK); 89 | 90 | save = false; 91 | } 92 | 93 | // save crash dump to game directory 94 | sprintf(filename, "%s/%s", basedir, crash_dmp); 95 | dbghelp = LoadLibrary("dbghelp.dll"); 96 | if (dbghelp != NULL) 97 | { 98 | typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, 99 | MINIDUMP_TYPE, 100 | CONST PMINIDUMP_EXCEPTION_INFORMATION, 101 | CONST PMINIDUMP_USER_STREAM_INFORMATION, 102 | CONST PMINIDUMP_CALLBACK_INFORMATION); 103 | MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); 104 | if (funcMiniDumpWriteDump != NULL) { 105 | HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 106 | HANDLE proc = GetCurrentProcess(); 107 | DWORD procid = GetCurrentProcessId(); 108 | MINIDUMP_EXCEPTION_INFORMATION mdei; 109 | 110 | mdei.ThreadId = GetCurrentThreadId(); 111 | mdei.ExceptionPointers = ep; 112 | mdei.ClientPointers = false; 113 | 114 | funcMiniDumpWriteDump(proc, procid, file, MiniDumpWithDataSegs | MiniDumpWithPrivateReadWriteMemory, &mdei, NULL, NULL); 115 | } 116 | FreeLibrary(dbghelp); 117 | } 118 | 119 | if(!ff8) 120 | { 121 | sprintf(filename, "%s/%s", basedir, "save/crash.ff7"); 122 | 123 | // try to dump the current savemap from memory 124 | // the savemap could be old, inconsistent or corrupted at this point 125 | // avoid playing from an emergency save if at all possible! 126 | if(save) 127 | { 128 | FILE *f = fopen(filename, "wb"); 129 | uint magic = 0x6277371; 130 | uint bitmask = 1; 131 | struct savemap dummy[14]; 132 | 133 | memset(dummy, 0, sizeof(dummy)); 134 | 135 | memcpy(ff7_externals.savemap->preview_location, save_name, sizeof(save_name)); 136 | 137 | ff7_externals.savemap->checksum = ff7_checksum(&(ff7_externals.savemap->preview_level)); 138 | 139 | fwrite(&magic, 4, 1, f); 140 | fwrite("", 1, 1, f); 141 | fwrite(&bitmask, 4, 1, f); 142 | fwrite(ff7_externals.savemap, sizeof(*ff7_externals.savemap), 1, f); 143 | fwrite(dummy, sizeof(dummy), 1, f); 144 | fclose(f); 145 | } 146 | } 147 | 148 | error("unhandled exception\n"); 149 | 150 | // let OS handle the crash 151 | SetUnhandledExceptionFilter(0); 152 | return EXCEPTION_CONTINUE_EXECUTION; 153 | } 154 | -------------------------------------------------------------------------------- /crashdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * crashdump.h - crash handler definitons 21 | */ 22 | 23 | #ifndef _CRASHDUMP_H_ 24 | #define _CRASHDUMP_H_ 25 | 26 | #include 27 | 28 | LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ctx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ctx.c - save/load functionality for the compressed texture cache 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "types.h" 28 | #include "gl.h" 29 | #include "cfg.h" 30 | #include "log.h" 31 | #include "globals.h" 32 | 33 | // compressed texture file header 34 | // 'format' field is OpenGL implementation-specific and not well defined in any way 35 | // sharing .ctx files between different setups is not recommended 36 | struct ctx_header 37 | { 38 | uint size; 39 | uint format; 40 | uint width; 41 | uint height; 42 | }; 43 | 44 | // save a compressed texture to disk 45 | bool write_ctx(char *filename, uint width, uint height, uint texture) 46 | { 47 | FILE *f; 48 | struct ctx_header header; 49 | char *data; 50 | GLint tmp; 51 | char *next = filename; 52 | 53 | glBindTexture(GL_TEXTURE_2D, texture); 54 | 55 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &tmp); 56 | 57 | if(!tmp) 58 | { 59 | error("Texture could not be compressed\n"); 60 | return false; 61 | } 62 | 63 | while((next = strchr(next, '/'))) 64 | { 65 | char tmp[sizeof(basedir) + 1024]; 66 | 67 | while(next[0] == '/') next++; 68 | 69 | strncpy(tmp, filename, next - filename); 70 | tmp[next - filename] = 0; 71 | 72 | if(trace_all) trace("Creating directory %s\n", tmp); 73 | 74 | mkdir(tmp); 75 | } 76 | 77 | if(fopen_s(&f, filename, "wb")) 78 | { 79 | error("couldn't open file %s for writing: %s", filename, _strerror(NULL)); 80 | return false; 81 | } 82 | 83 | header.width = width; 84 | header.height = height; 85 | 86 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &tmp); 87 | header.format = tmp; 88 | 89 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &tmp); 90 | header.size = tmp; 91 | 92 | fwrite(&header, sizeof(header), 1, f); 93 | 94 | data = driver_malloc(header.size); 95 | 96 | glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, data); 97 | 98 | fwrite(data, header.size, 1, f); 99 | 100 | driver_free(data); 101 | fclose(f); 102 | 103 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &tmp); 104 | 105 | if(trace_all) trace("Texture compression ratio: %i:1\n", (width * height * 4) / tmp); 106 | 107 | stats.ext_cache_size += tmp; 108 | 109 | return true; 110 | } 111 | 112 | // load a compressed texture from disk 113 | uint read_ctx(char *filename, uint *width, uint *height) 114 | { 115 | FILE *f; 116 | struct ctx_header header; 117 | char *data; 118 | GLuint texture; 119 | GLint tmp; 120 | 121 | if(fopen_s(&f, filename, "rb")) return 0; 122 | 123 | fread(&header, sizeof(header), 1, f); 124 | 125 | data = gl_get_pixel_buffer(header.size); 126 | 127 | fread(data, header.size, 1, f); 128 | 129 | *width = header.width; 130 | *height = header.height; 131 | 132 | gl_check_texture_dimensions(*width, *height, filename); 133 | 134 | texture = gl_commit_compressed_buffer(data, header.width, header.height, header.format, header.size); 135 | 136 | fclose(f); 137 | 138 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &tmp); 139 | 140 | if(trace_all) trace("Texture compression ratio: %i:1\n", ((*width) * (*height) * 4) / tmp); 141 | 142 | stats.ext_cache_size += tmp; 143 | 144 | return texture; 145 | } 146 | -------------------------------------------------------------------------------- /ctx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ctx.h - texture cache definitions 21 | */ 22 | 23 | #ifndef _CTX_H_ 24 | #define _CTX_H_ 25 | 26 | #include "types.h" 27 | 28 | bool write_ctx(char *filename, uint width, uint height, uint texture); 29 | uint read_ctx(char *filename, uint *width, uint *height); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /externals_102_de.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * externals_102_de.h - memory addresses for the german 1.02 version of FF7 21 | */ 22 | 23 | common_externals.directsound = (void *)0xDC2680; 24 | common_externals.debug_print = 0x664E00; 25 | common_externals.debug_print2 = 0x414EE0; 26 | common_externals.create_tex_header = (void *)0x688C16; 27 | common_externals.get_time = 0x660340; 28 | common_externals.midi_init = 0x6DE060; 29 | common_externals.get_midi_name = (void *)0x6E69B0; 30 | common_externals.play_midi = 0x6DE935; 31 | common_externals.stop_midi = 0x6DF70B; 32 | common_externals.cross_fade_midi = 0x6DF4CE; 33 | common_externals.pause_midi = 0x6DF65B; 34 | common_externals.restart_midi = 0x6DF6B3; 35 | common_externals.midi_status = 0x6DF793; 36 | common_externals.set_master_midi_volume = 0x6DF7BA; 37 | common_externals.set_midi_volume = 0x6DF817; 38 | common_externals.set_midi_volume_trans = 0x6DF92C; 39 | common_externals.set_midi_tempo = 0x6DFA9D; 40 | common_externals.draw_graphics_object = 0x66E611; 41 | common_externals.font_info = (void *)0x99EB68; 42 | common_externals.build_dialog_window = 0x7743B0; 43 | common_externals.load_tex_file = 0x688C66; 44 | 45 | ff7_externals.chocobo_fix = 0x70B512; 46 | ff7_externals.midi_fix = 0x6E0422; 47 | ff7_externals.snowboard_fix = (void *)0x94BA30; 48 | ff7_externals.cdcheck = 0x408FF3; 49 | ff7_externals.sub_665D9A = (void *)0x665D6A; 50 | ff7_externals.sub_671742 = (void *)0x671712; 51 | ff7_externals.sub_6B27A9 = (void *)0x6B2779; 52 | ff7_externals.sub_68D2B8 = (void *)0x68D288; 53 | ff7_externals.sub_665793 = (void *)0x665763; 54 | ff7_externals.matrix3x4 = (void *)0x67BC2B; 55 | ff7_externals.matrix4x3_multiply = 0x66CC0B; 56 | ff7_externals.sub_6B26C0 = 0x6B2690; 57 | ff7_externals.sub_6B2720 = 0x6B26F0; 58 | ff7_externals.sub_673F5C = 0x673F2C; 59 | ff7_externals.savemap = (void *)0xF38A68; 60 | ff7_externals.menu_objects = (void *)0xF39CF0; 61 | ff7_externals.magic_thread_start = 0x427928; 62 | ff7_externals.destroy_magic_effects = (void *)0x429322; 63 | ff7_externals.init_stuff = 0x40A091; 64 | -------------------------------------------------------------------------------- /externals_102_fr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * externals_102_fr.h - memory addresses for the french 1.02 version of FF7 21 | */ 22 | 23 | common_externals.directsound = (void *)0xDC36B0; 24 | common_externals.debug_print = 0x664DD0; 25 | common_externals.debug_print2 = 0x414EF0; 26 | common_externals.create_tex_header = (void *)0x688BE6; 27 | common_externals.get_time = 0x660310; 28 | common_externals.midi_init = 0x6DE000; 29 | common_externals.get_midi_name = (void *)0x6E6950; 30 | common_externals.play_midi = 0x6DE8D5; 31 | common_externals.stop_midi = 0x6DF6AB; 32 | common_externals.cross_fade_midi = 0x6DF46E; 33 | common_externals.pause_midi = 0x6DF5FB; 34 | common_externals.restart_midi = 0x6DF653; 35 | common_externals.midi_status = 0x6DF733; 36 | common_externals.set_master_midi_volume = 0x6DF75A; 37 | common_externals.set_midi_volume = 0x6DF7B7; 38 | common_externals.set_midi_volume_trans = 0x6DF8CC; 39 | common_externals.set_midi_tempo = 0x6DFA3D; 40 | common_externals.draw_graphics_object = 0x66E5E1; 41 | common_externals.font_info = (void *)0x99FB98; 42 | common_externals.build_dialog_window = 0x774690; 43 | common_externals.load_tex_file = 0x688C36; 44 | 45 | ff7_externals.chocobo_fix = 0x70B4B2; 46 | ff7_externals.midi_fix = 0x6E03C2; 47 | ff7_externals.snowboard_fix = (void *)0x94BA48; 48 | ff7_externals.cdcheck = 0x409003; 49 | ff7_externals.sub_665D9A = (void *)0x665D3A; 50 | ff7_externals.sub_671742 = (void *)0x6716E2; 51 | ff7_externals.sub_6B27A9 = (void *)0x6B2749; 52 | ff7_externals.sub_68D2B8 = (void *)0x68D258; 53 | ff7_externals.sub_665793 = (void *)0x665733; 54 | ff7_externals.matrix3x4 = (void *)0x67BBFB; 55 | ff7_externals.matrix4x3_multiply = 0x66CBDB; 56 | ff7_externals.sub_6B26C0 = 0x6B2660; 57 | ff7_externals.sub_6B2720 = 0x6B26C0; 58 | ff7_externals.sub_673F5C = 0x673EFC; 59 | ff7_externals.savemap = (void *)0xF39A78; 60 | ff7_externals.menu_objects = (void *)0xF3AD00; 61 | ff7_externals.magic_thread_start = 0x427938; 62 | ff7_externals.destroy_magic_effects = (void *)0x429332; 63 | ff7_externals.init_stuff = 0x40A0A1; 64 | -------------------------------------------------------------------------------- /externals_102_sp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * externals_102_sp.h - memory addresses for the spanish 1.02 version of FF7 21 | */ 22 | 23 | common_externals.directsound = (void *)0xDC4110; 24 | common_externals.debug_print = 0x664DD0; 25 | common_externals.debug_print2 = 0x414EF0; 26 | common_externals.create_tex_header = (void *)0x688BE6; 27 | common_externals.get_time = 0x660310; 28 | common_externals.midi_init = 0x6DE000; 29 | common_externals.get_midi_name = (void *)0x6E6950; 30 | common_externals.play_midi = 0x6DE8D5; 31 | common_externals.stop_midi = 0x6DF6AB; 32 | common_externals.cross_fade_midi = 0x6DF46E; 33 | common_externals.pause_midi = 0x6DF5FB; 34 | common_externals.restart_midi = 0x6DF653; 35 | common_externals.midi_status = 0x6DF733; 36 | common_externals.set_master_midi_volume = 0x6DF75A; 37 | common_externals.set_midi_volume = 0x6DF7B7; 38 | common_externals.set_midi_volume_trans = 0x6DF8CC; 39 | common_externals.set_midi_tempo = 0x6DFA3D; 40 | common_externals.draw_graphics_object = 0x66E5E1; 41 | common_externals.font_info = (void *)0x9A05F8; 42 | common_externals.build_dialog_window = 0x7747A0; 43 | common_externals.load_tex_file = 0x688C36; 44 | 45 | ff7_externals.chocobo_fix = 0x70B4B2; 46 | ff7_externals.midi_fix = 0x6E03C2; 47 | ff7_externals.snowboard_fix = (void *)0x94CA30; 48 | ff7_externals.cdcheck = 0x409003; 49 | ff7_externals.sub_665D9A = (void *)0x665D3A; 50 | ff7_externals.sub_671742 = (void *)0x6716E2; 51 | ff7_externals.sub_6B27A9 = (void *)0x6B2749; 52 | ff7_externals.sub_68D2B8 = (void *)0x68D258; 53 | ff7_externals.sub_665793 = (void *)0x665733; 54 | ff7_externals.matrix3x4 = (void *)0x67BBFB; 55 | ff7_externals.matrix4x3_multiply = 0x66CBDB; 56 | ff7_externals.sub_6B26C0 = 0x6B2660; 57 | ff7_externals.sub_6B2720 = 0x6B26C0; 58 | ff7_externals.sub_673F5C = 0x673EFC; 59 | ff7_externals.savemap = (void *)0xF3A548; 60 | ff7_externals.menu_objects = (void *)0xF3B7D0; 61 | ff7_externals.magic_thread_start = 0x427938; 62 | ff7_externals.destroy_magic_effects = (void *)0x429332; 63 | ff7_externals.init_stuff = 0x40A0A1; 64 | -------------------------------------------------------------------------------- /externals_102_us.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * externals_102_us.h - memory addresses for the english 1.02 version of FF7 21 | */ 22 | 23 | common_externals.directsound = (void *)0xDE6770; 24 | common_externals.debug_print = 0x664E30; 25 | common_externals.debug_print2 = 0x414EE0; 26 | common_externals.create_tex_header = (void *)0x688C46; 27 | common_externals.get_time = 0x660370; 28 | common_externals.midi_init = 0x741780; 29 | common_externals.get_midi_name = (void *)0x74A0D0; 30 | common_externals.play_midi = 0x742055; 31 | common_externals.stop_midi = 0x742E2B; 32 | common_externals.cross_fade_midi = 0x742BEE; 33 | common_externals.pause_midi = 0x742D7B; 34 | common_externals.restart_midi = 0x742DD3; 35 | common_externals.midi_status = 0x742EB3; 36 | common_externals.set_master_midi_volume = 0x742EDA; 37 | common_externals.set_midi_volume = 0x742F37; 38 | common_externals.set_midi_volume_trans = 0x74304C; 39 | common_externals.set_midi_tempo = 0x7431BD; 40 | common_externals.draw_graphics_object = 0x66E272; 41 | common_externals.font_info = (void *)0x99DDA8; 42 | common_externals.build_dialog_window = 0x6E97E0; 43 | common_externals.load_tex_file = 0x688C96; 44 | 45 | ff7_externals.chocobo_fix = 0x76EC32; 46 | ff7_externals.midi_fix = 0x743B42; 47 | ff7_externals.snowboard_fix = (void *)0x958328; 48 | ff7_externals.cdcheck = 0x408FF3; 49 | ff7_externals.sub_665D9A = (void *)0x665D9A; 50 | ff7_externals.sub_671742 = (void *)0x671742; 51 | ff7_externals.sub_6B27A9 = (void *)0x6B27A9; 52 | ff7_externals.sub_68D2B8 = (void *)0x68D2B8; 53 | ff7_externals.sub_665793 = (void *)0x665793; 54 | ff7_externals.matrix3x4 = (void *)0x67BC5B; 55 | ff7_externals.matrix4x3_multiply = 0x66CC3B; 56 | ff7_externals.sub_6B26C0 = 0x6B26C0; 57 | ff7_externals.sub_6B2720 = 0x6B2720; 58 | ff7_externals.sub_673F5C = 0x673F5C; 59 | ff7_externals.savemap = (void *)0xDBFD38; 60 | ff7_externals.menu_objects = (void *)0xDC0FC0; 61 | ff7_externals.magic_thread_start = 0x427928; 62 | ff7_externals.destroy_magic_effects = (void *)0x429322; 63 | ff7_externals.init_stuff = 0x40A091; 64 | -------------------------------------------------------------------------------- /fake_dd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * fake_dd.c - fake DirectDraw interface used to intercept FF8 movie player output 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "fake_dd.h" 27 | #include "types.h" 28 | #include "gl.h" 29 | #include "cfg.h" 30 | #include "log.h" 31 | #include "common.h" 32 | #include "globals.h" 33 | 34 | uint __stdcall fake_dd_blit_fast(struct ddsurface **this, uint unknown1, uint unknown2, struct ddsurface **target, LPRECT source, uint unknown3); 35 | uint __stdcall fake_ddsurface_get_pixelformat(struct ddsurface **this, LPDDPIXELFORMAT pf); 36 | uint __stdcall fake_ddsurface_get_surface_desc(struct ddsurface **this, LPDDSURFACEDESC2 sd); 37 | uint __stdcall fake_ddsurface_get_dd_interface(struct ddsurface **this, struct dddevice ***dd); 38 | uint __stdcall fake_ddsurface_get_palette(struct ddsurface **this, void **palette); 39 | uint __stdcall fake_ddsurface_lock(struct ddsurface **this, LPRECT dest, LPDDSURFACEDESC sd, uint flags, uint unused); 40 | uint __stdcall fake_ddsurface_unlock(struct ddsurface **this, LPRECT dest); 41 | uint __stdcall fake_ddsurface_islost(struct ddsurface **this); 42 | uint __stdcall fake_ddsurface_restore(struct ddsurface **this); 43 | uint __stdcall fake_dd_query_interface(struct dddevice **this, uint *iid, void **ppvobj); 44 | uint __stdcall fake_dd_addref(struct dddevice **this); 45 | uint __stdcall fake_dd_release(struct dddevice **this); 46 | uint __stdcall fake_dd_create_clipper(struct dddevice **this, DWORD flags, LPDIRECTDRAWCLIPPER *clipper); 47 | uint __stdcall fake_dd_create_palette(struct dddevice **this, LPPALETTEENTRY palette_entry, LPDIRECTDRAWPALETTE *palette, IUnknown *unused); 48 | uint __stdcall fake_dd_create_surface(struct dddevice **this, LPDDSURFACEDESC sd, LPDIRECTDRAWSURFACE *surface, IUnknown *unused); 49 | uint __stdcall fake_dd_get_caps(struct dddevice **this, LPDDCAPS halcaps, LPDDCAPS helcaps); 50 | uint __stdcall fake_dd_get_display_mode(struct dddevice **this, LPDDSURFACEDESC sd); 51 | uint __stdcall fake_dd_set_coop_level(struct dddevice **this, uint coop_level); 52 | uint __stdcall fake_d3d_get_caps(struct d3d2device **this, void *a, void *b); 53 | 54 | struct ddsurface fake_dd_surface = { 55 | fake_dd_query_interface, 56 | fake_dd_addref, 57 | fake_dd_release, 58 | 0, 59 | 0, 60 | 0, 61 | 0, 62 | fake_dd_blit_fast, 63 | 0, 64 | 0, 65 | 0, 66 | 0, 67 | 0, 68 | 0, 69 | 0, 70 | 0, 71 | 0, 72 | 0, 73 | 0, 74 | 0, 75 | fake_ddsurface_get_palette, 76 | fake_ddsurface_get_pixelformat, 77 | fake_ddsurface_get_surface_desc, 78 | 0, 79 | fake_ddsurface_islost, 80 | fake_ddsurface_lock, 81 | 0, 82 | fake_ddsurface_restore, 83 | 0, 84 | 0, 85 | 0, 86 | 0, 87 | fake_ddsurface_unlock, 88 | 0, 89 | 0, 90 | 0, 91 | fake_ddsurface_get_dd_interface, 92 | }; 93 | struct ddsurface *_fake_dd_back_surface = &fake_dd_surface; 94 | 95 | struct ddsurface fake_dd_front_surface = { 96 | fake_dd_query_interface, 97 | fake_dd_addref, 98 | fake_dd_release, 99 | 0, 100 | 0, 101 | 0, 102 | 0, 103 | fake_dd_blit_fast, 104 | 0, 105 | 0, 106 | 0, 107 | 0, 108 | 0, 109 | 0, 110 | 0, 111 | 0, 112 | 0, 113 | 0, 114 | 0, 115 | 0, 116 | fake_ddsurface_get_palette, 117 | fake_ddsurface_get_pixelformat, 118 | fake_ddsurface_get_surface_desc, 119 | 0, 120 | fake_ddsurface_islost, 121 | fake_ddsurface_lock, 122 | 0, 123 | fake_ddsurface_restore, 124 | 0, 125 | 0, 126 | 0, 127 | 0, 128 | fake_ddsurface_unlock, 129 | 0, 130 | 0, 131 | 0, 132 | fake_ddsurface_get_dd_interface, 133 | }; 134 | struct ddsurface *_fake_dd_front_surface = &fake_dd_front_surface; 135 | 136 | struct ddsurface fake_dd_temp_surface = { 137 | fake_dd_query_interface, 138 | fake_dd_addref, 139 | fake_dd_release, 140 | 0, 141 | 0, 142 | 0, 143 | 0, 144 | fake_dd_blit_fast, 145 | 0, 146 | 0, 147 | 0, 148 | 0, 149 | 0, 150 | 0, 151 | 0, 152 | 0, 153 | 0, 154 | 0, 155 | 0, 156 | 0, 157 | fake_ddsurface_get_palette, 158 | fake_ddsurface_get_pixelformat, 159 | fake_ddsurface_get_surface_desc, 160 | 0, 161 | fake_ddsurface_islost, 162 | fake_ddsurface_lock, 163 | 0, 164 | fake_ddsurface_restore, 165 | 0, 166 | 0, 167 | 0, 168 | 0, 169 | fake_ddsurface_unlock, 170 | 0, 171 | 0, 172 | 0, 173 | fake_ddsurface_get_dd_interface, 174 | }; 175 | struct ddsurface *_fake_dd_temp_surface = &fake_dd_temp_surface; 176 | 177 | struct dddevice fake_dddevice = { 178 | fake_dd_query_interface, 179 | fake_dd_addref, 180 | fake_dd_release, 181 | 0, 182 | fake_dd_create_clipper, 183 | fake_dd_create_palette, 184 | fake_dd_create_surface, 185 | 0, 186 | 0, 187 | 0, 188 | 0, 189 | fake_dd_get_caps, 190 | fake_dd_get_display_mode, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 0, 196 | 0, 197 | 0, 198 | fake_dd_set_coop_level, 199 | 0, 200 | 0, 201 | 0, 202 | }; 203 | struct dddevice *_fake_dddevice = &fake_dddevice; 204 | 205 | struct d3d2device fake_d3d2device = { 206 | fake_dd_query_interface, 207 | fake_dd_addref, 208 | fake_dd_release, 209 | fake_d3d_get_caps, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0, 220 | 0, 221 | 0, 222 | 0, 223 | 0, 224 | 0, 225 | 0, 226 | 0, 227 | 0, 228 | 0, 229 | 0, 230 | 0, 231 | 0, 232 | 0, 233 | 0, 234 | 0, 235 | }; 236 | struct d3d2device *_fake_d3d2device = &fake_d3d2device; 237 | 238 | uint __stdcall fake_dd_blit_fast(struct ddsurface **this, uint unknown1, uint unknown2, struct ddsurface **source, LPRECT src_rect, uint unknown3) 239 | { 240 | if(trace_fake_dx) trace("blit_fast\n"); 241 | 242 | return DD_OK; 243 | } 244 | 245 | uint __stdcall fake_ddsurface_get_pixelformat(struct ddsurface **this, LPDDPIXELFORMAT pf) 246 | { 247 | if(trace_fake_dx) trace("get_pixelformat\n"); 248 | 249 | pf->dwFlags = DDPF_RGB; 250 | pf->dwRGBBitCount = 24; 251 | pf->dwRBitMask = 0xFF0000; 252 | pf->dwGBitMask = 0xFF00; 253 | pf->dwBBitMask = 0xFF; 254 | 255 | return 0; 256 | } 257 | 258 | uint __stdcall fake_ddsurface_get_surface_desc(struct ddsurface **this, LPDDSURFACEDESC2 sd) 259 | { 260 | if(trace_fake_dx) trace("get_surface_desc\n"); 261 | 262 | return 0; 263 | } 264 | 265 | uint __stdcall fake_ddsurface_get_dd_interface(struct ddsurface **this, struct dddevice ***dd) 266 | { 267 | if(trace_fake_dx) trace("get_dd_interface\n"); 268 | 269 | *dd = &_fake_dddevice; 270 | return 0; 271 | } 272 | 273 | uint __stdcall fake_ddsurface_get_palette(struct ddsurface **this, void **palette) 274 | { 275 | if(trace_fake_dx) trace("get_palette\n"); 276 | 277 | //*palette = 0; 278 | 279 | return DDERR_UNSUPPORTED; 280 | } 281 | 282 | char *fake_dd_surface_buffer; 283 | 284 | uint __stdcall fake_ddsurface_lock(struct ddsurface **this, LPRECT dest, LPDDSURFACEDESC sd, uint flags, uint unused) 285 | { 286 | if(trace_fake_dx) trace("lock\n"); 287 | 288 | if(!fake_dd_surface_buffer) fake_dd_surface_buffer = driver_malloc(640 * 480 * 3); 289 | 290 | sd->lpSurface = fake_dd_surface_buffer; 291 | sd->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_LPSURFACE; 292 | 293 | sd->dwWidth = 640; 294 | sd->dwHeight = 480; 295 | sd->lPitch = 640 * 3; 296 | 297 | sd->ddpfPixelFormat.dwFlags = DDPF_RGB; 298 | sd->ddpfPixelFormat.dwRGBBitCount = 24; 299 | sd->ddpfPixelFormat.dwRBitMask = 0xFF0000; 300 | sd->ddpfPixelFormat.dwGBitMask = 0xFF00; 301 | sd->ddpfPixelFormat.dwBBitMask = 0xFF; 302 | 303 | return DD_OK; 304 | } 305 | 306 | GLuint movie_texture; 307 | 308 | uint __stdcall fake_ddsurface_unlock(struct ddsurface **this, LPRECT dest) 309 | { 310 | if(trace_fake_dx) trace("unlock\n"); 311 | 312 | glEnable(GL_TEXTURE_2D); 313 | 314 | if(movie_texture) glDeleteTextures(1, &movie_texture); 315 | 316 | movie_texture = gl_create_empty_texture(); 317 | 318 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 319 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 320 | 321 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 640, 480, 0, GL_BGR, GL_UNSIGNED_BYTE, fake_dd_surface_buffer); 322 | 323 | gl_draw_movie_quad_bgra(movie_texture, 640, 480); 324 | 325 | return DD_OK; 326 | } 327 | 328 | uint __stdcall fake_ddsurface_islost(struct ddsurface **this) 329 | { 330 | if(trace_fake_dx) trace("islost\n"); 331 | 332 | return DD_OK; 333 | } 334 | 335 | uint __stdcall fake_ddsurface_restore(struct ddsurface **this) 336 | { 337 | if(trace_fake_dx) trace("restore\n"); 338 | 339 | return DD_OK; 340 | } 341 | 342 | uint __stdcall fake_dd_query_interface(struct dddevice **this, uint *iid, void **ppvobj) 343 | { 344 | if(trace_fake_dx) trace("query_interface: 0x%p 0x%p 0x%p 0x%p\n", iid[0], iid[1], iid[2], iid[3]); 345 | 346 | if(iid[0] == 0x6C14DB80) 347 | { 348 | *ppvobj = this; 349 | return S_OK; 350 | } 351 | 352 | if(iid[0] == 0x57805885) 353 | { 354 | *ppvobj = &_fake_dd_temp_surface; 355 | return S_OK; 356 | } 357 | 358 | return E_NOINTERFACE; 359 | } 360 | 361 | uint __stdcall fake_dd_addref(struct dddevice **this) 362 | { 363 | if(trace_fake_dx) trace("addref\n"); 364 | 365 | return 1; 366 | } 367 | 368 | uint __stdcall fake_dd_release(struct dddevice **this) 369 | { 370 | if(trace_fake_dx) trace("release\n"); 371 | 372 | return 0; 373 | } 374 | 375 | uint __stdcall fake_dd_create_clipper(struct dddevice **this, DWORD flags, LPDIRECTDRAWCLIPPER *clipper) 376 | { 377 | if(trace_fake_dx) trace("create_clipper\n"); 378 | 379 | if(clipper == 0) return DDERR_INVALIDPARAMS; 380 | 381 | *clipper = 0; 382 | 383 | return DD_OK; 384 | } 385 | 386 | uint __stdcall fake_dd_create_palette(struct dddevice **this, LPPALETTEENTRY palette_entry, LPDIRECTDRAWPALETTE *palette, IUnknown *unused) 387 | { 388 | if(trace_fake_dx) trace("create_palette\n"); 389 | 390 | if(palette == 0) return DDERR_INVALIDPARAMS; 391 | 392 | *palette = 0; 393 | 394 | return DD_OK; 395 | } 396 | 397 | uint __stdcall fake_dd_create_surface(struct dddevice **this, LPDDSURFACEDESC sd, LPDIRECTDRAWSURFACE *surface, IUnknown *unused) 398 | { 399 | if(trace_fake_dx) trace("create_surface %ix%i\n", sd->dwWidth, sd->dwHeight); 400 | 401 | *surface = (LPDIRECTDRAWSURFACE)&_fake_dd_temp_surface; 402 | 403 | return 0; 404 | } 405 | 406 | uint __stdcall fake_dd_get_caps(struct dddevice **this, LPDDCAPS halcaps, LPDDCAPS helcaps) 407 | { 408 | if(trace_fake_dx) trace("get_caps\n"); 409 | 410 | halcaps->dwCaps = DDCAPS_BLTSTRETCH; 411 | return 0; 412 | } 413 | 414 | uint __stdcall fake_dd_get_display_mode(struct dddevice **this, LPDDSURFACEDESC sd) 415 | { 416 | if(trace_fake_dx) trace("get_display_mode\n"); 417 | 418 | sd->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT; 419 | 420 | sd->dwWidth = 1280; 421 | sd->dwHeight = 960; 422 | sd->lPitch = 1280 * 4; 423 | 424 | sd->ddpfPixelFormat.dwFlags = DDPF_RGB; 425 | sd->ddpfPixelFormat.dwRGBBitCount = 32; 426 | sd->ddpfPixelFormat.dwRBitMask = 0xFF; 427 | sd->ddpfPixelFormat.dwGBitMask = 0xFF00; 428 | sd->ddpfPixelFormat.dwBBitMask = 0xFF0000; 429 | sd->ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000; 430 | 431 | return 0; 432 | } 433 | 434 | uint __stdcall fake_dd_set_coop_level(struct dddevice **this, uint coop_level) 435 | { 436 | if(trace_fake_dx) trace("set_coop_level\n"); 437 | 438 | return 0; 439 | } 440 | 441 | uint __stdcall fake_d3d_get_caps(struct d3d2device **this, void *a, void *b) 442 | { 443 | if(trace_fake_dx) trace("d3d_get_caps\n"); 444 | 445 | memset(a, -1, 0xFC); 446 | memset(b, -1, 0xFC); 447 | 448 | return DD_OK; 449 | } 450 | -------------------------------------------------------------------------------- /fake_dd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * fake_dd.h - definitions for the fake DirectDraw interface used to intercept 21 | * FF8 movie player output 22 | */ 23 | 24 | #ifndef _FAKE_DD_H_ 25 | #define _FAKE_DD_H_ 26 | 27 | #include "types.h" 28 | 29 | struct ddsurface 30 | { 31 | void *query_interface; 32 | void *addref; 33 | void *release; 34 | uint field_C; 35 | uint field_10; 36 | uint field_14; 37 | uint field_18; 38 | void *blit_fast; 39 | uint field_20; 40 | uint field_24; 41 | uint field_28; 42 | uint field_2C; 43 | uint field_30; 44 | uint field_34; 45 | uint field_38; 46 | uint field_3C; 47 | uint field_40; 48 | uint field_44; 49 | uint field_48; 50 | uint field_4C; 51 | void *get_palette; 52 | void *get_pixelformat; 53 | void *get_surface_desc; 54 | uint field_5C; 55 | void *islost; 56 | void *lock; 57 | uint field_68; 58 | void *restore; 59 | uint field_70; 60 | uint field_74; 61 | uint field_78; 62 | uint field_7C; 63 | void *unlock; 64 | uint field_84; 65 | uint field_88; 66 | uint field_8C; 67 | void *get_dd_interface; 68 | }; 69 | 70 | struct dddevice 71 | { 72 | void *query_interface; 73 | void *addref; 74 | void *release; 75 | uint field_C; 76 | void *create_clipper; 77 | void *create_palette; 78 | void *create_surface; 79 | uint field_1C; 80 | uint field_20; 81 | uint field_24; 82 | uint field_28; 83 | void *get_caps; 84 | void *get_display_mode; 85 | uint field_34; 86 | uint field_38; 87 | uint field_3C; 88 | uint field_40; 89 | uint field_44; 90 | uint field_48; 91 | uint field_4C; 92 | void *set_coop_level; 93 | uint field_54; 94 | uint field_58; 95 | uint field_5C; 96 | }; 97 | 98 | struct d3d2device 99 | { 100 | void *query_interface; 101 | void *addref; 102 | void *release; 103 | void *get_caps; 104 | uint field_10; 105 | uint field_14; 106 | uint field_18; 107 | uint field_1C; 108 | uint field_20; 109 | uint field_24; 110 | uint field_28; 111 | uint field_2C; 112 | uint field_30; 113 | uint field_34; 114 | uint field_38; 115 | uint field_3C; 116 | uint junk[10]; 117 | void *set_transform; 118 | uint field_6C; 119 | uint field_70; 120 | uint field_74; 121 | void *draw_indexed_primitive; 122 | }; 123 | 124 | extern struct ddsurface *_fake_dd_back_surface; 125 | extern struct ddsurface *_fake_dd_temp_surface; 126 | extern struct ddsurface *_fake_dd_front_surface; 127 | extern struct dddevice *_fake_dddevice; 128 | extern struct d3d2device *_fake_d3d2device; 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /ff7/battle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7/battle.c - replacement routines for FF7's battle system 21 | */ 22 | 23 | #include "../types.h" 24 | #include "../common.h" 25 | #include "../ff7.h" 26 | #include "../log.h" 27 | #include "../globals.h" 28 | 29 | void magic_thread_start(void (*func)()) 30 | { 31 | ff7_externals.destroy_magic_effects(); 32 | 33 | /* 34 | * Original function creates a separate thread but the code is not thread 35 | * safe in any way! Luckily modern PCs are fast enough to load magic 36 | * effects synchronously. 37 | */ 38 | func(); 39 | } 40 | -------------------------------------------------------------------------------- /ff7/defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7/defs.h - definitions & prototypes for FF7 code replacements 21 | */ 22 | 23 | #ifndef _DEFS_H_ 24 | #define _DEFS_H_ 25 | 26 | // battle 27 | void magic_thread_start(void (*func)()); 28 | 29 | // misc 30 | uint get_equipment_stats(uint party_index, uint type); 31 | void kernel2_reset_counters(); 32 | char *kernel2_add_section(uint size); 33 | char *kernel2_get_text(uint section_base, uint string_id, uint section_offset); 34 | 35 | // field 36 | void field_load_textures(struct ff7_game_obj *game_object, struct struc_3 *struc_3); 37 | void field_layer2_pick_tiles(short x_offset, short y_offset); 38 | void char_addhp(uint party_index, word amount); 39 | void char_addmp(uint party_index, word amount); 40 | 41 | // file 42 | FILE *open_lgp_file(char *filename, uint mode); 43 | void close_lgp_file(FILE *fd); 44 | extern char lgp_names[18][256]; 45 | bool lgp_chdir(char *path); 46 | struct lgp_file *lgp_open_file(char *filename, uint lgp_num); 47 | bool lgp_seek_file(uint offset, uint lgp_num); 48 | uint lgp_read(uint lgp_num, char *dest, uint size); 49 | uint lgp_read_file(struct lgp_file *file, uint lgp_num, char *dest, uint size); 50 | uint lgp_get_filesize(struct lgp_file *file, uint lgp_num); 51 | void close_file(struct ff7_file *file); 52 | struct ff7_file *open_file(struct file_context *file_context, char *filename); 53 | uint __read_file(uint count, void *buffer, struct ff7_file *file); 54 | bool read_file(uint count, void *buffer, struct ff7_file *file); 55 | uint __read(FILE *file, char *buffer, uint count); 56 | bool write_file(uint count, void *buffer, struct ff7_file *file); 57 | uint get_filesize(struct ff7_file *file); 58 | uint tell_file(struct ff7_file *file); 59 | void seek_file(struct ff7_file *file, uint offset); 60 | char *make_pc_name(struct file_context *file_context, struct ff7_file *file, char *filename); 61 | 62 | // graphics 63 | void destroy_d3d2_indexed_primitive(struct indexed_primitive *ip); 64 | bool ff7gl_load_group(uint group_num, struct matrix_set *matrix_set, struct p_hundred *_hundred_data, struct p_group *_group_data, struct polygon_data *polygon_data, struct ff7_polygon_set *polygon_set, struct ff7_game_obj *game_object); 65 | struct tex_header *sub_673F5C(struct struc_91 *struc91); 66 | void draw_single_triangle(struct nvertex *vertices); 67 | void sub_6B2720(struct indexed_primitive *ip); 68 | void draw_3d_model(uint current_frame, struct anim_header *anim_header, struct struc_110 *struc_110, struct hrc_data *hrc_data, struct ff7_game_obj *game_object); 69 | 70 | // loaders 71 | struct anim_header *load_animation(struct file_context *file_context, char *filename); 72 | struct battle_hrc_header *read_battle_hrc(bool use_file_context, struct file_context *file_context, char *filename); 73 | struct polygon_data *load_p_file(struct file_context *file_context, bool create_lists, char *filename); 74 | void destroy_tex_header(struct ff7_tex_header *tex_header); 75 | struct ff7_tex_header *load_tex_file(struct file_context *file_context, char *filename); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /ff7/field.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7/field.c - replacement routines for FF7's field module 21 | */ 22 | 23 | #include "../types.h" 24 | #include "../common.h" 25 | #include "../ff7.h" 26 | #include "../log.h" 27 | #include "../globals.h" 28 | 29 | /* 30 | * This file contains the changes necessary to support subtractive and 25% 31 | * blending modes in field backgrounds. Texture pages where these blending 32 | * modes are used are duplicated and the tile data modified to point to these 33 | * new pages which have the correct blending mode set. 34 | */ 35 | 36 | // helper function initializes page dst, copies texture from src and applies 37 | // blend_mode 38 | void field_load_textures_helper(struct ff7_game_obj *game_object, struct struc_3 *struc_3, uint src, uint dst, uint blend_mode) 39 | { 40 | struct ff7_tex_header *tex_header; 41 | 42 | ff7_externals.make_struc3(blend_mode, struc_3); 43 | 44 | tex_header = (struct ff7_tex_header *)common_externals.create_tex_header(); 45 | 46 | ff7_externals.field_layers[dst]->tex_header = tex_header; 47 | 48 | if(ff7_externals.field_layers[src]->type == 1) ff7_externals.make_field_tex_header_pal(tex_header); 49 | if(ff7_externals.field_layers[src]->type == 2) ff7_externals.make_field_tex_header(tex_header); 50 | 51 | struc_3->tex_header = tex_header; 52 | 53 | if(src != dst) 54 | { 55 | ff7_externals.field_layers[dst]->image_data = external_malloc(256 * 256); 56 | memcpy(ff7_externals.field_layers[dst]->image_data, ff7_externals.field_layers[src]->image_data, 256 * 256); 57 | } 58 | 59 | tex_header->image_data = ff7_externals.field_layers[dst]->image_data; 60 | 61 | tex_header->file.pc_name = external_malloc(1024); 62 | sprintf(tex_header->file.pc_name, "field/%s/%s_%02i", strchr(ff7_externals.field_file_name, '\\') + 1, strchr(ff7_externals.field_file_name, '\\') + 1, src); 63 | 64 | ff7_externals.field_layers[dst]->graphics_object = ff7_externals._load_texture(1, PT_S2D, struc_3, 0, game_object->dx_sfx_something); 65 | ff7_externals.field_layers[dst]->present = true; 66 | } 67 | 68 | void field_load_textures(struct ff7_game_obj *game_object, struct struc_3 *struc_3) 69 | { 70 | uint i; 71 | 72 | ff7_externals.field_convert_type2_layers(); 73 | 74 | for(i = 0; i < 29; i++) 75 | { 76 | uint blend_mode = 4; 77 | 78 | if(!ff7_externals.field_layers[i]->present) continue; 79 | 80 | if(ff7_externals.field_layers[i]->type == 1) 81 | { 82 | if(i >= 24) blend_mode = 0; 83 | else if(i >= 15) blend_mode = 1; 84 | } 85 | else if(ff7_externals.field_layers[i]->type == 2) 86 | { 87 | if(i >= 40) blend_mode = 0; 88 | else if(i >= 33) blend_mode = 1; 89 | } 90 | else glitch("unknown field layer type %i\n", ff7_externals.field_layers[i]->type); 91 | 92 | field_load_textures_helper(game_object, struc_3, i, i, blend_mode); 93 | 94 | // these magic numbers have been gleaned from original source data 95 | // the missing blend modes in question are used in exactly these pages 96 | // and copying them in this manner does not risk overwriting any other 97 | // data 98 | if(i >= 15 && i <= 18 && ff7_externals.field_layers[i]->type == 1) field_load_textures_helper(game_object, struc_3, i, i + 14, 2); 99 | if(i >= 15 && i <= 20 && ff7_externals.field_layers[i]->type == 1) field_load_textures_helper(game_object, struc_3, i, i + 18, 3); 100 | } 101 | 102 | *ff7_externals.layer2_end_page += 18; 103 | } 104 | 105 | void field_layer2_pick_tiles(short x_offset, short y_offset) 106 | { 107 | int x_add = (320 - x_offset) * 2; 108 | int y_add = (224 - y_offset) * 2; 109 | uint i; 110 | struct field_tile *layer2_tiles = *ff7_externals.field_layer2_tiles; 111 | 112 | if(*ff7_externals.field_special_y_offset > 0 && y_offset <= 8) y_offset -= *ff7_externals.field_special_y_offset * 2; 113 | 114 | for(i = 0; i < *ff7_externals.field_layer2_tiles_num; i++) 115 | { 116 | uint tile_index = (*ff7_externals.field_layer2_palette_sort)[i] & 0xFFFF; 117 | uint page; 118 | int x; 119 | int y; 120 | 121 | if(layer2_tiles[tile_index].anim_group && !(ff7_externals.field_anim_state[layer2_tiles[tile_index].anim_group] & layer2_tiles[tile_index].anim_bitmask)) continue; 122 | 123 | layer2_tiles[tile_index].field_1040 = 1; 124 | 125 | x = layer2_tiles[tile_index].x * 2 + x_add; 126 | y = layer2_tiles[tile_index].y * 2 + y_add; 127 | 128 | if(layer2_tiles[tile_index].use_fx_page) page = layer2_tiles[tile_index].fx_page; 129 | else page = layer2_tiles[tile_index].page; 130 | 131 | if(layer2_tiles[tile_index].use_fx_page && layer2_tiles[tile_index].blend_mode == 2) page += 14; 132 | if(layer2_tiles[tile_index].use_fx_page && layer2_tiles[tile_index].blend_mode == 3) page += 18; 133 | 134 | ff7_externals.add_page_tile((float)x, (float)y, layer2_tiles[tile_index].z, layer2_tiles[tile_index].u, layer2_tiles[tile_index].v, layer2_tiles[tile_index].palette_index, page); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /ff7/loaders.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7/loaders.c - replacement routines for FF7 file loaders 21 | */ 22 | 23 | #include "../types.h" 24 | #include "../common.h" 25 | #include "../ff7.h" 26 | #include "../globals.h" 27 | #include "../log.h" 28 | 29 | #include "defs.h" 30 | 31 | uint get_frame_data_size(struct anim_header *anim_header) 32 | { 33 | if(!anim_header) return 0; 34 | 35 | return (anim_header->num_bones * sizeof(struct point3d) + sizeof(struct anim_frame_header)) * anim_header->num_frames; 36 | } 37 | 38 | // load .a file, save modpath name somewhere we can retrieve it later (unused) 39 | struct anim_header *load_animation(struct file_context *file_context, char *filename) 40 | { 41 | struct ff7_file *file = open_file(file_context, filename); 42 | struct anim_header *ret; 43 | uint size; 44 | uint i; 45 | uint data_pointer; 46 | 47 | if(trace_loaders) 48 | { 49 | if(file_context->use_lgp) trace("reading animation file: %s/%s\n", lgp_names[file_context->lgp_num], filename); 50 | else trace("reading animation file: %s\n", filename); 51 | } 52 | 53 | if(!file) goto error; 54 | 55 | ret = common_externals.alloc_read_file(sizeof(*ret), 1, (struct file *)file); 56 | 57 | if(!ret) goto error; 58 | if(ret->version.version != 1) goto error; 59 | 60 | ret->use_matrix_array = false; 61 | ret->matrix_array = 0; 62 | ret->current_matrix_array = 0; 63 | 64 | size = get_frame_data_size(ret); 65 | if(!size) goto error; 66 | 67 | ret->frame_data = common_externals.alloc_read_file(size, 1, (struct file *)file); 68 | if(!ret->frame_data) goto error; 69 | 70 | ret->anim_frames = external_calloc(sizeof(struct anim_frame), ret->num_frames); 71 | 72 | data_pointer = (uint)ret->frame_data; 73 | 74 | for(i = 0; i < ret->num_frames; i++) 75 | { 76 | ret->anim_frames[i].header = (void *)data_pointer; 77 | data_pointer += sizeof(struct anim_frame_header); 78 | ret->anim_frames[i].data = (void *)data_pointer; 79 | data_pointer += sizeof(struct point3d) * ret->num_bones; 80 | } 81 | 82 | ret->file.pc_name = make_pc_name(file_context, file, filename); 83 | 84 | close_file(file); 85 | return ret; 86 | 87 | error: 88 | ff7_externals.destroy_animation(ret); 89 | close_file(file); 90 | return 0; 91 | }; 92 | 93 | // load battle HRC file (does not save modpath name) 94 | struct battle_hrc_header *read_battle_hrc(bool use_file_context, struct file_context *file_context, char *filename) 95 | { 96 | struct battle_hrc_header *ret; 97 | struct battle_chdir_struc olddir; 98 | char hrc_filename[200]; 99 | uint size; 100 | 101 | if(use_file_context) ff7_externals.battle_context_chdir(file_context, &olddir); 102 | else ff7_externals.battle_regular_chdir(&olddir); 103 | 104 | ff7_externals.swap_extension("D", filename, hrc_filename); 105 | 106 | if(trace_loaders) 107 | { 108 | if(file_context->use_lgp) trace("reading battle hrc file: %s/%s\n", lgp_names[file_context->lgp_num], hrc_filename); 109 | else trace("reading battle hrc file: %s\n", hrc_filename); 110 | } 111 | 112 | ret = common_externals.alloc_get_file(file_context, &size, hrc_filename); 113 | 114 | if(size < sizeof(*ret)) 115 | { 116 | ff7_externals.destroy_battle_hrc(false, ret); 117 | return 0; 118 | } 119 | 120 | ret->bone_data = 0; 121 | 122 | if(ret->bones > 0) ret->bone_data = (struct battle_hrc_bone *)&ret[1]; 123 | 124 | if(use_file_context) ff7_externals.battle_context_olddir(file_context, &olddir); 125 | else ff7_externals.battle_regular_olddir(&olddir); 126 | 127 | return ret; 128 | } 129 | 130 | // load .p file, save modpath name somewhere we can retrieve it later (unused) 131 | struct polygon_data *load_p_file(struct file_context *file_context, bool create_lists, char *filename) 132 | { 133 | struct polygon_data *ret = ff7_externals.create_polygon_data(false, 0); 134 | struct ff7_file *file = open_file(file_context, filename); 135 | 136 | if(trace_loaders) 137 | { 138 | if(file_context->use_lgp) trace("reading p file: %s/%s\n", lgp_names[file_context->lgp_num], filename); 139 | else trace("reading p file: %s\n", filename); 140 | } 141 | 142 | if(!file) goto error; 143 | if(!read_file(sizeof(*ret), ret, file)) goto error; 144 | 145 | ret->vertdata = 0; 146 | ret->normaldata = 0; 147 | ret->field_48 = 0; 148 | ret->texcoorddata = 0; 149 | ret->vertexcolordata = 0; 150 | ret->polycolordata = 0; 151 | ret->edgedata = 0; 152 | ret->polydata = 0; 153 | ret->pc_name = make_pc_name(file_context, file, filename); 154 | ret->field_64 = 0; 155 | ret->hundredsdata = 0; 156 | ret->groupdata = 0; 157 | ret->lists = 0; 158 | ret->boundingboxdata = 0; 159 | ret->normindextabledata = 0; 160 | 161 | if(ret->version != 1) 162 | { 163 | error("invalid version in polygon file %s\n", filename); 164 | goto error; 165 | } 166 | 167 | if(ret->field_2C) unexpected("oops, missed some .p data\n"); 168 | 169 | ret->vertdata = common_externals.alloc_read_file(sizeof(*ret->vertdata), ret->numverts, (struct file *)file); 170 | ret->normaldata = common_externals.alloc_read_file(sizeof(*ret->normaldata), ret->numnormals, (struct file *)file); 171 | ret->field_48 = common_externals.alloc_read_file(sizeof(*ret->field_48), ret->field_14, (struct file *)file); 172 | ret->texcoorddata = common_externals.alloc_read_file(sizeof(*ret->texcoorddata), ret->numtexcoords, (struct file *)file); 173 | ret->vertexcolordata = common_externals.alloc_read_file(sizeof(*ret->vertexcolordata), ret->numvertcolors, (struct file *)file); 174 | ret->polycolordata = common_externals.alloc_read_file(sizeof(*ret->polycolordata), ret->numpolys, (struct file *)file); 175 | ret->edgedata = common_externals.alloc_read_file(sizeof(*ret->edgedata), ret->numedges, (struct file *)file); 176 | ret->polydata = common_externals.alloc_read_file(sizeof(*ret->polydata), ret->numpolys, (struct file *)file); 177 | external_free(common_externals.alloc_read_file(sizeof(struct p_polygon), ret->field_28, (struct file *)file)); 178 | ret->field_64 = common_externals.alloc_read_file(3, ret->field_2C, (struct file *)file); 179 | ret->hundredsdata = common_externals.alloc_read_file(sizeof(*ret->hundredsdata), ret->numhundreds, (struct file *)file); 180 | ret->groupdata = common_externals.alloc_read_file(sizeof(*ret->groupdata), ret->numgroups, (struct file *)file); 181 | ret->boundingboxdata = common_externals.alloc_read_file(sizeof(*ret->boundingboxdata), ret->numboundingboxes, (struct file *)file); 182 | if(ret->has_normindextable) ret->normindextabledata = common_externals.alloc_read_file(sizeof(*ret->normindextabledata), ret->numverts, (struct file *)file); 183 | 184 | if(create_lists) ff7_externals.create_polygon_lists(ret); 185 | 186 | close_file(file); 187 | return ret; 188 | 189 | error: 190 | ff7_externals.free_polygon_data(ret); 191 | close_file(file); 192 | return 0; 193 | } 194 | 195 | void destroy_tex_header(struct ff7_tex_header *tex_header) 196 | { 197 | if(!tex_header) return; 198 | 199 | if((uint)tex_header->file.pc_name > 32) external_free(tex_header->file.pc_name); 200 | 201 | external_free(tex_header->old_palette_data); 202 | external_free(tex_header->palette_colorkey); 203 | external_free(tex_header->tex_format.palette_data); 204 | external_free(tex_header->image_data); 205 | 206 | external_free(tex_header); 207 | } 208 | 209 | // load .tex file, save modpath name somewhere we can retrieve it later 210 | struct ff7_tex_header *load_tex_file(struct file_context *file_context, char *filename) 211 | { 212 | struct ff7_tex_header *ret = (struct ff7_tex_header *)common_externals.create_tex_header(); 213 | struct ff7_file *file = open_file(file_context, filename); 214 | 215 | if(!file) goto error; 216 | if(!read_file(sizeof(*ret), ret, file)) goto error; 217 | 218 | ret->image_data = 0; 219 | ret->old_palette_data = 0; 220 | ret->palette_colorkey = 0; 221 | ret->tex_format.palette_data = 0; 222 | 223 | if(ret->version != 1) goto error; 224 | else 225 | { 226 | if(ret->tex_format.use_palette) 227 | { 228 | ret->tex_format.palette_data = common_externals.alloc_read_file(4, ret->tex_format.palette_size, (struct file *)file); 229 | if(!ret->tex_format.palette_data) goto error; 230 | } 231 | 232 | ret->image_data = common_externals.alloc_read_file(ret->tex_format.bytesperpixel, ret->tex_format.width * ret->tex_format.height, (struct file *)file); 233 | if(!ret->image_data) goto error; 234 | 235 | if(ret->use_palette_colorkey) 236 | { 237 | ret->palette_colorkey = common_externals.alloc_read_file(1, ret->palettes, (struct file *)file); 238 | if(!ret->palette_colorkey) goto error; 239 | } 240 | } 241 | 242 | ret->file.pc_name = make_pc_name(file_context, file, filename); 243 | 244 | close_file(file); 245 | return ret; 246 | 247 | error: 248 | destroy_tex_header(ret); 249 | close_file(file); 250 | return 0; 251 | } 252 | -------------------------------------------------------------------------------- /ff7/misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7/misc.c - replacement routines for miscellaneous FF7 functions 21 | */ 22 | 23 | #include "../types.h" 24 | #include "../ff7.h" 25 | #include "../common.h" 26 | #include "../globals.h" 27 | #include "../cfg.h" 28 | #include "../log.h" 29 | 30 | // MDEF fix 31 | uint get_equipment_stats(uint party_index, uint type) 32 | { 33 | uint character = ff7_externals.party_member_to_char_map[ff7_externals.savemap->party_members[party_index]]; 34 | 35 | switch(type) 36 | { 37 | case 0: 38 | return ff7_externals.weapon_data_array[ff7_externals.savemap->chars[character].equipped_weapon].attack_stat; 39 | break; 40 | case 1: 41 | return ff7_externals.armor_data_array[ff7_externals.savemap->chars[character].equipped_armor].defense_stat; 42 | break; 43 | case 2: 44 | return 0; 45 | break; 46 | case 3: 47 | return mdef_fix ? ff7_externals.armor_data_array[ff7_externals.savemap->chars[character].equipped_armor].mdef_stat : 0; 48 | break; 49 | 50 | default: return 0; 51 | } 52 | } 53 | 54 | char *kernel2_sections[20]; 55 | uint kernel2_section_counter; 56 | 57 | void kernel2_reset_counters() 58 | { 59 | uint i; 60 | 61 | if(trace_all) trace("kernel2 reset\n"); 62 | 63 | for(i = 0; i < kernel2_section_counter; i++) free(kernel2_sections[i]); 64 | 65 | kernel2_section_counter = 0; 66 | } 67 | 68 | char *kernel2_add_section(uint size) 69 | { 70 | char *ret = driver_malloc(size); 71 | 72 | if(trace_all) trace("kernel2 add section %i (%i)\n", kernel2_section_counter, size); 73 | 74 | kernel2_sections[kernel2_section_counter++] = ret; 75 | 76 | return ret; 77 | } 78 | 79 | char *kernel2_get_text(uint section_base, uint string_id, uint section_offset) 80 | { 81 | char *section = kernel2_sections[section_base + section_offset]; 82 | 83 | if(trace_all) trace("kernel2 get text (%i+%i:%i)\n", section_base, section_offset, string_id); 84 | 85 | return §ion[((word *)section)[string_id]]; 86 | } 87 | -------------------------------------------------------------------------------- /ff7_data.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aali132/ff7_opengl/bfb9a37628f188d909a046bf626803534e28e2de/ff7_data.h -------------------------------------------------------------------------------- /ff7_opengl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * ff7_opengl.c - FF7 specific code and loading routine 21 | */ 22 | 23 | #include "compile_cfg.h" 24 | 25 | #include "types.h" 26 | #include "cfg.h" 27 | #include "ff7.h" 28 | #include "common.h" 29 | #include "globals.h" 30 | #include "gl.h" 31 | #include "log.h" 32 | #include "patch.h" 33 | #include "movies.h" 34 | #include "music.h" 35 | #include "ff7/defs.h" 36 | 37 | #include "ff7_data.h" 38 | 39 | void ff7_read_basedir() 40 | { 41 | uint basedir_length = sizeof(basedir); 42 | HKEY ff7_regkey; 43 | 44 | RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Square Soft, Inc.\\Final Fantasy VII", 0, KEY_QUERY_VALUE, &ff7_regkey); 45 | RegQueryValueEx(ff7_regkey, "AppPath", 0, 0, basedir, &basedir_length); 46 | basedir[sizeof(basedir) - 1] = 0; 47 | } 48 | 49 | unsigned char midi_fix[] = {0x8B, 0x4D, 0x14}; 50 | word snowboard_fix[] = {0x0F, 0x10, 0x0F}; 51 | 52 | static uint noop() { return 0; } 53 | 54 | struct ff7_gfx_driver *ff7_load_driver(struct ff7_game_obj *game_object) 55 | { 56 | struct ff7_gfx_driver *ret; 57 | 58 | ff7_read_basedir(); 59 | 60 | read_cfg(); 61 | 62 | common_externals.add_texture_format = game_object->externals->add_texture_format; 63 | common_externals.assert_calloc = game_object->externals->assert_calloc; 64 | common_externals.assert_malloc = game_object->externals->assert_malloc; 65 | common_externals.assert_free = game_object->externals->assert_free; 66 | common_externals.create_palette_for_tex = game_object->externals->create_palette_for_tex; 67 | common_externals.create_texture_format = game_object->externals->create_texture_format; 68 | common_externals.create_texture_set = game_object->externals->create_texture_set; 69 | common_externals.generic_light_polygon_set = game_object->externals->generic_light_polygon_set; 70 | common_externals.generic_load_group = game_object->externals->generic_load_group; 71 | common_externals.get_game_object = game_object->externals->get_game_object; 72 | ff7_externals.sub_6A2865 = game_object->externals->sub_6A2865; 73 | common_externals.make_pixelformat = game_object->externals->make_pixelformat; 74 | 75 | ff7_data(); 76 | 77 | if(width == 1280) MessageBoxA(hwnd, "Using this driver with the old high-res patch is NOT recommended, there will be glitches.", "Warning", 0); 78 | 79 | game_object->d3d2_flag = 1; 80 | game_object->nvidia_fix = 0; 81 | 82 | game_object->window_title = "Final Fantasy VII"; 83 | 84 | // DirectInput hack, try to reacquire on any error 85 | memset_code(ff7_externals.dinput_getdata2 + 0x65, 0x90, 9); 86 | memset_code(ff7_externals.dinput_getstate2 + 0x3C, 0x90, 9); 87 | memset_code(ff7_externals.dinput_getstate2 + 0x7E, 0x90, 5); 88 | memset_code(ff7_externals.dinput_acquire_keyboard + 0x31, 0x90, 5); 89 | 90 | replace_function(ff7_externals.dinput_createdevice_mouse, noop); 91 | 92 | if(more_ff7_debug) replace_function(common_externals.debug_print2, external_debug_print2); 93 | 94 | replace_function(ff7_externals.draw_3d_model, draw_3d_model); 95 | 96 | // sub_6B27A9 hack, replace d3d code 97 | memset_code((uint)ff7_externals.sub_6B27A9 + 25, 0x90, 6); 98 | replace_function(ff7_externals.sub_6B26C0, draw_single_triangle); 99 | replace_function(ff7_externals.sub_6B2720, sub_6B2720); 100 | 101 | // replace framebuffer access routine with our own version 102 | replace_function(ff7_externals.sub_673F5C, sub_673F5C); 103 | 104 | replace_function(ff7_externals.destroy_d3d2_indexed_primitive, destroy_d3d2_indexed_primitive); 105 | 106 | replace_function(ff7_externals.load_animation, load_animation); 107 | replace_function(ff7_externals.read_battle_hrc, read_battle_hrc); 108 | replace_function(common_externals.destroy_tex_header, destroy_tex_header); 109 | replace_function(ff7_externals.load_p_file, load_p_file); 110 | replace_function(common_externals.load_tex_file, load_tex_file); 111 | 112 | replace_function(ff7_externals.field_load_textures, field_load_textures); 113 | replace_function(ff7_externals.field_layer2_pick_tiles, field_layer2_pick_tiles); 114 | patch_code_byte(ff7_externals.field_draw_everything + 0xE2, 0x1D); 115 | patch_code_byte(ff7_externals.field_draw_everything + 0x353, 0x1D); 116 | 117 | if(transparent_dialogs) memset_code(common_externals.build_dialog_window + 0x1842, 0x90, 6); 118 | 119 | replace_function(ff7_externals.get_equipment_stats, get_equipment_stats); 120 | 121 | replace_function(common_externals.open_file, open_file); 122 | replace_function(common_externals.read_file, read_file); 123 | replace_function(common_externals.__read_file, __read_file); 124 | replace_function(ff7_externals.__read, __read); 125 | replace_function(common_externals.write_file, write_file); 126 | replace_function(common_externals.close_file, close_file); 127 | replace_function(common_externals.get_filesize, get_filesize); 128 | replace_function(common_externals.tell_file, tell_file); 129 | replace_function(common_externals.seek_file, seek_file); 130 | replace_function(ff7_externals.open_lgp_file, open_lgp_file); 131 | replace_function(ff7_externals.lgp_chdir, lgp_chdir); 132 | replace_function(ff7_externals.lgp_open_file, lgp_open_file); 133 | replace_function(ff7_externals.lgp_read, lgp_read); 134 | replace_function(ff7_externals.lgp_read_file, lgp_read_file); 135 | replace_function(ff7_externals.lgp_get_filesize, lgp_get_filesize); 136 | replace_function(ff7_externals.lgp_seek_file, lgp_seek_file); 137 | 138 | if(use_new_timer) 139 | { 140 | // replace rdtsc timing 141 | replace_function(common_externals.get_time, qpc_get_time); 142 | 143 | // override the timer calibration 144 | QueryPerformanceFrequency((LARGE_INTEGER *)&game_object->_countspersecond); 145 | game_object->countspersecond = (double)game_object->_countspersecond; 146 | } 147 | 148 | replace_function(ff7_externals.magic_thread_start, magic_thread_start); 149 | 150 | replace_function(ff7_externals.kernel2_reset_counters, kernel2_reset_counters); 151 | replace_function(ff7_externals.kernel2_add_section, kernel2_add_section); 152 | replace_function(ff7_externals.kernel2_get_text, kernel2_get_text); 153 | patch_code_uint(ff7_externals.kernel_load_kernel2 + 0x1D, 20 * 65536); 154 | 155 | // chocobo crash fix 156 | memset_code(ff7_externals.chocobo_fix - 12, 0x90, 36); 157 | 158 | // midi transition crash fix 159 | memcpy_code(ff7_externals.midi_fix, midi_fix, sizeof(midi_fix)); 160 | memset_code(ff7_externals.midi_fix + sizeof(midi_fix), 0x90, 18 - sizeof(midi_fix)); 161 | 162 | // prevent FF7 from trying to cleanup the built-in midi player if we're going to replace it 163 | if(strlen(music_plugin) > 0) replace_function(ff7_externals.cleanup_midi, noop); 164 | 165 | // snowboard crash fix 166 | memcpy(ff7_externals.snowboard_fix, snowboard_fix, sizeof(snowboard_fix)); 167 | 168 | // coaster aim fix 169 | patch_code_byte(ff7_externals.coaster_sub_5EE150 + 0x129, 5); 170 | patch_code_byte(ff7_externals.coaster_sub_5EE150 + 0x14A, 5); 171 | patch_code_byte(ff7_externals.coaster_sub_5EE150 + 0x16D, 5); 172 | patch_code_byte(ff7_externals.coaster_sub_5EE150 + 0x190, 5); 173 | 174 | ret = external_calloc(1, sizeof(*ret)); 175 | 176 | ret->init = common_init; 177 | ret->cleanup = common_cleanup; 178 | ret->lock = common_lock; 179 | ret->unlock = common_unlock; 180 | ret->flip = common_flip; 181 | ret->clear = common_clear; 182 | ret->clear_all= common_clear_all; 183 | ret->setviewport = common_setviewport; 184 | ret->setbg = common_setbg; 185 | ret->prepare_polygon_set = common_prepare_polygon_set; 186 | ret->load_group = common_load_group; 187 | ret->setmatrix = common_setmatrix; 188 | ret->unload_texture = common_unload_texture; 189 | ret->load_texture = common_load_texture; 190 | ret->palette_changed = common_palette_changed; 191 | ret->write_palette = common_write_palette; 192 | ret->blendmode = common_blendmode; 193 | ret->light_polygon_set = common_externals.generic_light_polygon_set; 194 | ret->field_64 = common_field_64; 195 | ret->setrenderstate = common_setrenderstate; 196 | ret->_setrenderstate = common_setrenderstate; 197 | ret->__setrenderstate = common_setrenderstate; 198 | ret->field_74 = common_field_74; 199 | ret->field_78 = common_field_78; 200 | ret->draw_deferred = common_draw_deferred; 201 | ret->field_80 = common_field_80; 202 | ret->field_84 = common_field_84; 203 | ret->begin_scene = common_begin_scene; 204 | ret->end_scene = common_end_scene; 205 | ret->field_90 = common_field_90; 206 | ret->setrenderstate_flat2D = common_setrenderstate_2D; 207 | ret->setrenderstate_smooth2D = common_setrenderstate_2D; 208 | ret->setrenderstate_textured2D = common_setrenderstate_2D; 209 | ret->setrenderstate_paletted2D = common_setrenderstate_2D; 210 | ret->_setrenderstate_paletted2D = common_setrenderstate_2D; 211 | ret->draw_flat2D = common_draw_2D; 212 | ret->draw_smooth2D = common_draw_2D; 213 | ret->draw_textured2D = common_draw_2D; 214 | ret->draw_paletted2D = common_draw_paletted2D; 215 | ret->setrenderstate_flat3D = common_setrenderstate_3D; 216 | ret->setrenderstate_smooth3D = common_setrenderstate_3D; 217 | ret->setrenderstate_textured3D = common_setrenderstate_3D; 218 | ret->setrenderstate_paletted3D = common_setrenderstate_3D; 219 | ret->_setrenderstate_paletted3D = common_setrenderstate_3D; 220 | ret->draw_flat3D = common_draw_3D; 221 | ret->draw_smooth3D = common_draw_3D; 222 | ret->draw_textured3D = common_draw_3D; 223 | ret->draw_paletted3D = common_draw_paletted3D; 224 | ret->setrenderstate_flatlines = common_setrenderstate_2D; 225 | ret->setrenderstate_smoothlines = common_setrenderstate_2D; 226 | ret->draw_flatlines = common_draw_lines; 227 | ret->draw_smoothlines = common_draw_lines; 228 | ret->field_EC = common_field_EC; 229 | 230 | return ret; 231 | } 232 | 233 | void ff7_post_init() 234 | { 235 | movie_init(); 236 | if(strlen(music_plugin) > 0) music_init(); 237 | } 238 | -------------------------------------------------------------------------------- /ff7music/music.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published by 4 | * the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "types.h" 22 | 23 | // logging functions, printf-style, trace output is not visible in a release build of the driver 24 | void (*trace)(char *, ...); 25 | void (*info)(char *, ...); 26 | void (*glitch)(char *, ...); 27 | void (*error)(char *, ...); 28 | 29 | // directsound interface, not useful for the FF7Music plugin 30 | IDirectSound **directsound; 31 | 32 | uint current_id = 0; 33 | 34 | // send a message to be intercepted by FF7Music 35 | void send_ff7music(char *fmt, ...) 36 | { 37 | va_list args; 38 | char msg[0x100]; 39 | 40 | va_start(args, fmt); 41 | 42 | vsnprintf(msg, sizeof(msg), fmt, args); 43 | 44 | OutputDebugStringA(msg); 45 | } 46 | 47 | BOOL APIENTRY DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) 48 | { 49 | return TRUE; 50 | } 51 | 52 | // called once just after the plugin has been loaded, is a pointer to FF7s own directsound pointer 53 | __declspec(dllexport) void music_init(void *plugin_trace, void *plugin_info, void *plugin_glitch, void *plugin_error, IDirectSound **plugin_directsound, const char *plugin_basedir) 54 | { 55 | trace = plugin_trace; 56 | info = plugin_info; 57 | glitch = plugin_glitch; 58 | error = plugin_error; 59 | directsound = plugin_directsound; 60 | 61 | info("FF7Music helper plugin loaded\n"); 62 | } 63 | 64 | // start playing some music, is the name of the MIDI file without the .mid extension 65 | __declspec(dllexport) void play_music(char *midi, uint id) 66 | { 67 | if(id == current_id) return; 68 | 69 | send_ff7music("reading midi file: %s.mid\n", midi); 70 | 71 | current_id = id; 72 | } 73 | 74 | __declspec(dllexport) void stop_music() 75 | { 76 | send_ff7music("MIDI stop\n"); 77 | } 78 | 79 | // cross fade to a new song 80 | __declspec(dllexport) void cross_fade_music(char *midi, uint id, uint time) 81 | { 82 | if(id == current_id) return; 83 | 84 | stop_music(); 85 | play_music(midi, id); 86 | } 87 | 88 | __declspec(dllexport) void pause_music() 89 | { 90 | 91 | } 92 | 93 | __declspec(dllexport) void resume_music() 94 | { 95 | 96 | } 97 | 98 | // return true if music is playing, false if it isn't 99 | // it's important for some field scripts that this function returns true atleast once when a song has been requested 100 | // 101 | // even if there's nothing to play because of errors/missing files you cannot return false every time 102 | __declspec(dllexport) bool music_status() 103 | { 104 | static bool dummy = true; 105 | 106 | dummy = !dummy; 107 | 108 | return dummy; 109 | } 110 | 111 | __declspec(dllexport) void set_master_music_volume(uint volume) 112 | { 113 | 114 | } 115 | 116 | __declspec(dllexport) void set_music_volume(uint volume) 117 | { 118 | 119 | } 120 | 121 | // make a volume transition 122 | __declspec(dllexport) void set_music_volume_trans(uint volume, uint step) 123 | { 124 | uint from = volume ? 0 : 127; 125 | 126 | send_ff7music("MIDI set volume trans: %d->%d; step=%d\n", from, volume, step); 127 | } 128 | 129 | __declspec(dllexport) void set_music_tempo(unsigned char tempo) 130 | { 131 | 132 | } 133 | -------------------------------------------------------------------------------- /ff7music/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H_ 2 | #define _TYPES_H_ 3 | 4 | typedef unsigned short word; 5 | typedef unsigned int uint; 6 | typedef unsigned int bool; 7 | 8 | #define true 1 9 | #define false 0 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ffmpeg_movies/ffmpeg_glue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // this glue is necessary to make FFMpeg work with MSVCRT 11 | 12 | int strncasecmp(const char *a, const char *b, size_t n) { return _strnicmp(a, b, n); } 13 | int strcasecmp(const char *a, const char *b) { return _stricmp(a, b); } 14 | int usleep(int t) { Sleep(t / 1000); return 0; } 15 | 16 | // ffmpeg needs these symbols, but they're not really used 17 | void gettimeofday() {} 18 | void snprintf() {} 19 | 20 | int *__errno() 21 | { 22 | return _errno(); 23 | } 24 | 25 | #undef sinf 26 | #undef cosf 27 | #undef log10f 28 | #undef powf 29 | #undef truncf 30 | #undef ldexpf 31 | #undef expf 32 | #undef logf 33 | #undef exp2f 34 | float sinf(float a) { return (float)sin(a); } 35 | float cosf(float a) { return (float)cos(a); } 36 | float log10f(float a) { return (float)log10(a); } 37 | float powf(float a, float b) { return (float)pow(a, b); } 38 | float truncf(float a) { return (float)(a > 0 ? floor(a) : ceil(a)); } 39 | float ldexpf(float a, int b) { return (float)ldexp(a, b); } 40 | float expf(float a) { return (float)exp(a); } 41 | float logf(float a) { return (float)log(a); } 42 | #define exp2(x) exp((x) * 0.693147180559945) 43 | float exp2f(float a) { return (float)exp2(a); } 44 | 45 | #define FP_NAN 0 46 | #define FP_INFINITE 1 47 | #define FP_ZERO 2 48 | #define FP_SUBNORMAL 3 49 | #define FP_NORMAL 4 50 | 51 | int __fpclassifyd(double a) 52 | { 53 | if(_isnan(a)) return FP_NAN; 54 | if(!_finite(a)) return FP_INFINITE; 55 | if(a == 0.0) return FP_ZERO; 56 | 57 | return FP_NORMAL; 58 | } 59 | 60 | static float CBRT2 = 1.25992104989487316477f; 61 | static float CBRT4 = 1.58740105196819947475f; 62 | 63 | float cbrtf( float xx ) 64 | { 65 | int e, rem, sign; 66 | float x, z; 67 | 68 | x = xx; 69 | if( x == 0 ) 70 | return( 0.0f ); 71 | if( x > 0 ) 72 | sign = 1; 73 | else 74 | { 75 | sign = -1; 76 | x = -x; 77 | } 78 | 79 | z = x; 80 | x = frexpf( x, &e ); 81 | 82 | x = (((-0.13466110473359520655053f * x 83 | + 0.54664601366395524503440f ) * x 84 | - 0.95438224771509446525043f ) * x 85 | + 1.1399983354717293273738f ) * x 86 | + 0.40238979564544752126924f; 87 | 88 | if( e >= 0 ) 89 | { 90 | rem = e; 91 | e /= 3; 92 | rem -= 3*e; 93 | if( rem == 1 ) 94 | x *= CBRT2; 95 | else if( rem == 2 ) 96 | x *= CBRT4; 97 | } 98 | 99 | else 100 | { 101 | e = -e; 102 | rem = e; 103 | e /= 3; 104 | rem -= 3*e; 105 | if( rem == 1 ) 106 | x /= CBRT2; 107 | else if( rem == 2 ) 108 | x /= CBRT4; 109 | e = -e; 110 | } 111 | 112 | x = ldexpf( x, e ); 113 | 114 | x -= ( x - (z/(x*x)) ) * 0.333333333333f; 115 | 116 | if( sign < 0 ) 117 | x = -x; 118 | return(x); 119 | } 120 | 121 | int ffmpeg_open(char *name, int access, int mode) 122 | { 123 | access &= 0xFFF; 124 | 125 | access |= O_BINARY; 126 | 127 | return open(name, access); 128 | } 129 | 130 | int ffmpeg_lseek(int fd, int pos, int whence) 131 | { 132 | return lseek(fd, pos, whence); 133 | } 134 | -------------------------------------------------------------------------------- /ffmpeg_movies/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H_ 2 | #define _TYPES_H_ 3 | 4 | typedef unsigned short word; 5 | typedef unsigned int uint; 6 | typedef unsigned int bool; 7 | 8 | #define true 1 9 | #define false 0 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /gl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * gl.h - definitions used by OpenGL renderer 21 | */ 22 | 23 | #ifndef _DRIVER_GL_H_ 24 | #define _DRIVER_GL_H_ 25 | 26 | #include 27 | 28 | #include "types.h" 29 | #include "common.h" 30 | #include "matrix.h" 31 | 32 | #define VERTEX 1 33 | #define LVERTEX 2 34 | #define TLVERTEX 3 35 | 36 | #define BLEND_AVG 0 37 | #define BLEND_ADD 1 38 | #define BLEND_SUB 2 39 | #define BLEND_25P 3 40 | #define BLEND_NONE 4 41 | 42 | struct driver_state 43 | { 44 | struct texture_set *texture_set; 45 | uint texture_handle; 46 | uint blend_mode; 47 | uint viewport[4]; 48 | bool fb_texture; 49 | bool wireframe; 50 | bool texture_filter; 51 | bool cullface; 52 | bool nocull; 53 | bool depthtest; 54 | bool depthmask; 55 | bool shademode; 56 | bool alphatest; 57 | uint alphafunc; 58 | uint alpharef; 59 | struct matrix world_matrix; 60 | struct matrix d3dprojection_matrix; 61 | }; 62 | 63 | struct deferred_draw 64 | { 65 | GLenum primitivetype; 66 | uint vertextype; 67 | uint vertexcount; 68 | uint count; 69 | struct nvertex *vertices; 70 | word *indices; 71 | bool clip; 72 | bool mipmap; 73 | struct driver_state state; 74 | double z; 75 | bool drawn; 76 | }; 77 | 78 | struct gl_texture_set 79 | { 80 | uint textures; 81 | bool force_filter; 82 | bool force_zsort; 83 | }; 84 | 85 | extern struct matrix d3dviewport_matrix; 86 | 87 | extern struct driver_state current_state; 88 | 89 | extern GLuint current_program; 90 | 91 | extern uint max_texture_size; 92 | 93 | void gl_draw_movie_quad_bgra(GLuint, int, int); 94 | void gl_draw_movie_quad_yuv(GLuint *, int, int, bool); 95 | GLuint gl_create_program(char *vertex_file, char *fragment_file, char *name); 96 | void gl_use_post_program(); 97 | void gl_use_main_program(); 98 | void gl_use_yuv_program(); 99 | void gl_save_state(struct driver_state *dest); 100 | void gl_load_state(struct driver_state *src); 101 | bool gl_defer_draw(GLenum primitivetype, uint vertextype, struct nvertex *vertices, uint vertexcount, word *indices, uint count, bool clip, bool mipmap); 102 | void gl_draw_deferred(); 103 | void gl_check_deferred(struct texture_set *texture_set); 104 | bool gl_special_case(GLenum primitivetype, uint vertextype, struct nvertex *vertices, uint vertexcount, word *indices, uint count, struct graphics_object *graphics_object, bool clip, bool mipmap); 105 | void gl_draw_with_lighting(struct indexed_primitive *ip, bool clip, struct matrix *model_matrix); 106 | void gl_draw_indexed_primitive(GLenum, uint, struct nvertex *, uint, word *, uint, struct graphics_object *, bool clip, bool mipmap); 107 | void gl_set_world_matrix(struct matrix *matrix); 108 | void gl_set_d3dprojection_matrix(struct matrix *matrix); 109 | void gl_set_blend_func(uint); 110 | void gl_check_texture_dimensions(uint width, uint height, char *source); 111 | GLuint gl_create_empty_texture(); 112 | GLuint gl_create_texture(void *data, uint width, uint height, uint format, uint internalformat, uint size, bool generate_mipmaps); 113 | void gl_init_pbo_ring(); 114 | void *gl_get_pixel_buffer(uint size); 115 | GLuint gl_commit_pixel_buffer(void *data, uint width, uint height, uint format, bool generate_mipmaps); 116 | GLuint gl_compress_pixel_buffer(void *data, uint width, uint height, uint format); 117 | GLuint gl_commit_compressed_buffer(void *data, uint width, uint height, uint format, uint size); 118 | void gl_replace_texture(struct texture_set *texture_set, uint palette_index, uint new_texture); 119 | void gl_upload_texture(struct texture_set *texture_set, uint palette_index, void *image_data, uint format); 120 | void gl_bind_texture_set(struct texture_set *); 121 | void gl_set_texture(GLuint); 122 | bool gl_init_indirect(); 123 | bool gl_init_postprocessing(); 124 | void gl_prepare_flip(); 125 | void gl_prepare_render(); 126 | bool gl_load_shaders(); 127 | bool gl_draw_text(uint x, uint y, uint color, uint alpha, char *fmt, ...); 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /gl/deferred.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * gl/deferred.c - implements triangle re-ordering to achieve correct blending 21 | */ 22 | 23 | #include "../types.h" 24 | #include "../gl.h" 25 | #include "../macro.h" 26 | #include "../log.h" 27 | 28 | bool nodefer = false; 29 | 30 | #define DEFERRED_MAX 1024 31 | 32 | struct deferred_draw *deferred_draws; 33 | uint num_deferred; 34 | 35 | // re-order and save a draw call for later processing 36 | bool gl_defer_draw(GLenum primitivetype, uint vertextype, struct nvertex *vertices, uint vertexcount, word *indices, uint count, bool clip, bool mipmap) 37 | { 38 | uint tri; 39 | uint mode = getmode_cached()->driver_mode; 40 | bool *tri_deferred; 41 | float *tri_z; 42 | uint defer_index = 0; 43 | 44 | if(!deferred_draws) deferred_draws = driver_calloc(sizeof(*deferred_draws), DEFERRED_MAX); 45 | 46 | // global disable 47 | if(nodefer) return false; 48 | 49 | // output will not be consistent if depth testing is disabled, this call 50 | // cannot be re-ordered 51 | if(!current_state.depthtest) 52 | { 53 | return false; 54 | } 55 | 56 | // framebuffer textures should not be re-ordered 57 | if(current_state.fb_texture) 58 | { 59 | return false; 60 | } 61 | 62 | if(current_state.blend_mode != BLEND_NONE) 63 | { 64 | if(current_state.blend_mode != BLEND_AVG) 65 | { 66 | // be conservative with non-standard blending modes 67 | if(mode != MODE_MENU && mode != MODE_BATTLE) return false; 68 | } 69 | } 70 | else 71 | { 72 | // fancy_transparency brought us here, blending was not enabled for 73 | // this texture originally 74 | 75 | if(!current_state.texture_set) return false; 76 | else 77 | { 78 | VOBJ(texture_set, texture_set, current_state.texture_set); 79 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 80 | 81 | // texture format does not support alpha, re-order is not necessary 82 | if(!VREF(texture_set, ogl.external) && VREF(tex_header, tex_format.alpha_bits) < 2) return false; 83 | } 84 | } 85 | 86 | // quads are used for some GUI elements, we do not need to re-order these 87 | if(primitivetype != GL_TRIANGLES) return false; 88 | 89 | if(num_deferred + count / 3 > DEFERRED_MAX) 90 | { 91 | glitch("deferred draw queue overflow\n"); 92 | return false; 93 | } 94 | 95 | tri_deferred = driver_calloc(sizeof(*tri_deferred), count / 3); 96 | tri_z = driver_calloc(sizeof(*tri_z), count / 3); 97 | 98 | // calculate screen space average Z coordinate for each triangle 99 | for(tri = 0; tri < count / 3; tri++) 100 | { 101 | uint i; 102 | 103 | for(i = 0; i < 3; i++) 104 | { 105 | if(vertextype == TLVERTEX) tri_z[tri] += vertices[indices[tri * 3 + i]]._.z; 106 | else 107 | { 108 | struct point4d world; 109 | struct point4d proj; 110 | struct point4d view; 111 | transform_point_w(¤t_state.world_matrix, &vertices[indices[tri * 3 + i]]._, &world); 112 | transform_point4d(¤t_state.d3dprojection_matrix, &world, &proj); 113 | transform_point4d(&d3dviewport_matrix, &proj, &view); 114 | tri_z[tri] += view.z / view.w; 115 | } 116 | } 117 | 118 | tri_z[tri] /= 3.0f; 119 | } 120 | 121 | // arrange triangles into layers based on Z coordinates calculated above 122 | // each layer will be drawn separately 123 | while(defer_index < count / 3) 124 | { 125 | float z = tri_z[defer_index]; 126 | uint tri_num = 0; 127 | uint defer = num_deferred; 128 | uint vert_index = 0; 129 | 130 | for(tri = 0; tri < count / 3; tri++) if(tri_z[tri] == z) tri_num++; 131 | 132 | deferred_draws[defer].count = tri_num * 3; 133 | deferred_draws[defer].clip = clip; 134 | deferred_draws[defer].mipmap = mipmap; 135 | deferred_draws[defer].primitivetype = primitivetype; 136 | deferred_draws[defer].vertextype = vertextype; 137 | deferred_draws[defer].vertexcount = tri_num * 3; 138 | deferred_draws[defer].indices = driver_malloc(sizeof(*indices) * tri_num * 3); 139 | deferred_draws[defer].vertices = driver_malloc(sizeof(*vertices) * tri_num * 3); 140 | gl_save_state(&deferred_draws[defer].state); 141 | deferred_draws[defer].drawn = false; 142 | deferred_draws[defer].z = z; 143 | 144 | for(tri = 0; tri < count / 3 && vert_index < tri_num * 3; tri++) 145 | { 146 | if(tri_z[tri] == z) 147 | { 148 | memcpy(&deferred_draws[defer].vertices[vert_index + 0], &vertices[indices[tri * 3 + 0]], sizeof(*vertices)); 149 | memcpy(&deferred_draws[defer].vertices[vert_index + 1], &vertices[indices[tri * 3 + 1]], sizeof(*vertices)); 150 | memcpy(&deferred_draws[defer].vertices[vert_index + 2], &vertices[indices[tri * 3 + 2]], sizeof(*vertices)); 151 | deferred_draws[defer].indices[vert_index + 0] = vert_index + 0; 152 | deferred_draws[defer].indices[vert_index + 1] = vert_index + 1; 153 | deferred_draws[defer].indices[vert_index + 2] = vert_index + 2; 154 | 155 | vert_index += 3; 156 | 157 | tri_deferred[tri] = true; 158 | } 159 | } 160 | 161 | if(vert_index < tri_num * 3) error("deferred draw z mismatch\n"); 162 | 163 | num_deferred++; 164 | 165 | while(defer_index < count / 3 && tri_deferred[defer_index]) defer_index++; 166 | } 167 | 168 | driver_free(tri_deferred); 169 | driver_free(tri_z); 170 | 171 | return true; 172 | } 173 | 174 | // draw all the layers we've accumulated in the correct order and reset queue 175 | void gl_draw_deferred() 176 | { 177 | struct driver_state saved_state; 178 | 179 | if(num_deferred == 0) return; 180 | 181 | gl_save_state(&saved_state); 182 | 183 | nodefer = true; 184 | 185 | stats.deferred += num_deferred; 186 | 187 | while(true) 188 | { 189 | uint i; 190 | double z = -1.0; 191 | uint next = -1; 192 | 193 | for(i = 0; i < num_deferred; i++) 194 | { 195 | if(deferred_draws[i].z > z && !deferred_draws[i].drawn) 196 | { 197 | next = i; 198 | z = deferred_draws[i].z; 199 | } 200 | } 201 | 202 | if(next == -1) break; 203 | 204 | gl_load_state(&deferred_draws[next].state); 205 | internal_set_renderstate(V_DEPTHTEST, 1, 0); 206 | internal_set_renderstate(V_DEPTHMASK, 1, 0); 207 | 208 | gl_draw_indexed_primitive(deferred_draws[next].primitivetype, 209 | deferred_draws[next].vertextype, 210 | deferred_draws[next].vertices, 211 | deferred_draws[next].vertexcount, 212 | deferred_draws[next].indices, 213 | deferred_draws[next].count, 214 | 0, 215 | deferred_draws[next].clip, 216 | deferred_draws[next].mipmap 217 | ); 218 | 219 | driver_free(deferred_draws[next].vertices); 220 | driver_free(deferred_draws[next].indices); 221 | deferred_draws[next].drawn = true; 222 | } 223 | 224 | num_deferred = 0; 225 | 226 | nodefer = false; 227 | 228 | gl_load_state(&saved_state); 229 | } 230 | 231 | // a texture is being unloaded, invalidate any pending draw calls associated 232 | // with it and perform the necessary cleanup 233 | void gl_check_deferred(struct texture_set *texture_set) 234 | { 235 | uint i; 236 | 237 | for(i = 0; i < num_deferred; i++) 238 | { 239 | if(deferred_draws[i].state.texture_set == texture_set) 240 | { 241 | driver_free(deferred_draws[i].vertices); 242 | driver_free(deferred_draws[i].indices); 243 | deferred_draws[i].drawn = true; 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /gl/shader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * gl/shader.c - support functions for loading/using OpenGL shaders 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "../types.h" 27 | #include "../log.h" 28 | 29 | uint main_program = 0; 30 | uint post_program = 0; 31 | uint yuv_program = 0; 32 | 33 | uint current_program = 0; 34 | 35 | // read plaintext shader source file 36 | char *read_source(const char *file) 37 | { 38 | uint size, read = 0; 39 | FILE *f; 40 | struct stat s; 41 | char *buffer; 42 | char filename[BASEDIR_LENGTH + 1024]; 43 | 44 | _snprintf(filename, sizeof(filename), "%s/%s", basedir, file); 45 | 46 | if(stat(filename, &s)) 47 | { 48 | error("failed to stat file %s\n", filename); 49 | return 0; 50 | } 51 | 52 | size = s.st_size; 53 | buffer = driver_malloc(size + 1); 54 | 55 | f = fopen(filename, "r"); 56 | 57 | if(!f) 58 | { 59 | error("couldn't open file %s for reading: %s", filename, _strerror(NULL)); 60 | driver_free(buffer); 61 | return 0; 62 | } 63 | 64 | while(read < size) 65 | { 66 | uint ret = fread(&buffer[read], 1, size - read, f); 67 | 68 | if(ret == 0 && feof(f)) break; 69 | 70 | read += ret; 71 | } 72 | 73 | buffer[read] = 0; 74 | 75 | return buffer; 76 | } 77 | 78 | void printShaderInfoLog(GLuint obj, char *name) 79 | { 80 | int infologLength = 0; 81 | char *infoLog; 82 | 83 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength); 84 | 85 | if(infologLength > 1) 86 | { 87 | infoLog = (char *)driver_malloc(infologLength); 88 | glGetShaderInfoLog(obj, infologLength, 0, infoLog); 89 | info("%s shader compile log:\n%s\n", name, infoLog); 90 | driver_free(infoLog); 91 | } 92 | } 93 | 94 | void printProgramInfoLog(GLuint obj, char *name) 95 | { 96 | int infologLength = 0; 97 | char *infoLog; 98 | 99 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength); 100 | 101 | if(infologLength > 1) 102 | { 103 | infoLog = (char *)driver_malloc(infologLength); 104 | glGetProgramInfoLog(obj, infologLength, 0, infoLog); 105 | info("%s program link log:\n%s\n", name, infoLog); 106 | driver_free(infoLog); 107 | } 108 | } 109 | 110 | // create shader program from vertex and fragment components, either one is 111 | // optional 112 | GLuint gl_create_program(char *vertex_file, char *fragment_file, char *name) 113 | { 114 | GLint status = GL_FALSE; 115 | GLuint program = glCreateProgram(); 116 | GLuint vshader, fshader; 117 | 118 | if(vertex_file) 119 | { 120 | char *vs = read_source(vertex_file); 121 | 122 | if(vs == 0) 123 | { 124 | glDeleteProgram(program); 125 | return 0; 126 | } 127 | 128 | vshader = glCreateShader(GL_VERTEX_SHADER); 129 | 130 | glShaderSource(vshader, 1, &vs, NULL); 131 | 132 | driver_free(vs); 133 | 134 | glCompileShader(vshader); 135 | printShaderInfoLog(vshader, "vertex"); 136 | glAttachShader(program, vshader); 137 | } 138 | 139 | if(fragment_file) 140 | { 141 | char *fs = read_source(fragment_file); 142 | 143 | if(fs == 0) 144 | { 145 | if(vertex_file) glDeleteShader(vshader); 146 | glDeleteProgram(program); 147 | return 0; 148 | } 149 | 150 | fshader = glCreateShader(GL_FRAGMENT_SHADER); 151 | 152 | glShaderSource(fshader, 1, &fs, NULL); 153 | 154 | driver_free(fs); 155 | 156 | glCompileShader(fshader); 157 | printShaderInfoLog(fshader, "fragment"); 158 | glAttachShader(program, fshader); 159 | } 160 | 161 | glLinkProgram(program); 162 | printProgramInfoLog(program, name); 163 | 164 | glGetProgramiv(program, GL_LINK_STATUS, &status); 165 | 166 | if(status != GL_TRUE) 167 | { 168 | if(vertex_file) glDeleteShader(vshader); 169 | if(fragment_file) glDeleteShader(fshader); 170 | glDeleteProgram(program); 171 | return 0; 172 | } 173 | 174 | return program; 175 | } 176 | 177 | // enable postprocessing shader 178 | void gl_use_post_program() 179 | { 180 | glUseProgram(post_program); 181 | current_program = post_program; 182 | 183 | if(post_program != 0) 184 | { 185 | glUniform1i(glGetUniformLocation(current_program, "tex"), 0); 186 | glUniform1f(glGetUniformLocation(current_program, "width"), (float)internal_size_x); 187 | glUniform1f(glGetUniformLocation(current_program, "height"), (float)internal_size_y); 188 | } 189 | } 190 | 191 | // enable main rendering shader 192 | void gl_use_main_program() 193 | { 194 | glUseProgram(main_program); 195 | current_program = main_program; 196 | 197 | if(main_program != 0) 198 | { 199 | glUniform1i(glGetUniformLocation(current_program, "tex"), 0); 200 | } 201 | } 202 | 203 | // enable YUV texture shader 204 | void gl_use_yuv_program() 205 | { 206 | glUseProgram(yuv_program); 207 | current_program = yuv_program; 208 | 209 | if(yuv_program != 0) 210 | { 211 | glUniform1i(glGetUniformLocation(current_program, "y_tex"), 0); 212 | glUniform1i(glGetUniformLocation(current_program, "u_tex"), 1); 213 | glUniform1i(glGetUniformLocation(current_program, "v_tex"), 2); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /gl/special_case.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * gl/special_case.c - rendering special cases, quirks or improved effects 21 | */ 22 | 23 | #include 24 | 25 | #include "../types.h" 26 | #include "../gl.h" 27 | #include "../cfg.h" 28 | #include "../macro.h" 29 | #include "../log.h" 30 | #include "../ff8.h" 31 | #include "../saveload.h" 32 | 33 | #define SAFE_GFXOBJ_CHECK(X, Y) ((X) && (X) == (struct graphics_object *)(Y)) 34 | 35 | // rendering special cases, returns true if the draw call has been handled in 36 | // some way and should not be rendered normally 37 | // it is generally not safe to modify source data directly, a copy should be 38 | // made and rendered separately 39 | bool gl_special_case(GLenum primitivetype, uint vertextype, struct nvertex *vertices, uint vertexcount, word *indices, uint count, struct graphics_object *graphics_object, bool clip, bool mipmap) 40 | { 41 | uint mode = getmode_cached()->driver_mode; 42 | VOBJ(texture_set, texture_set, current_state.texture_set); 43 | bool defer = false; 44 | 45 | if(fancy_transparency && current_state.texture_set && current_state.blend_mode == BLEND_NONE) 46 | { 47 | // restore original blend mode for non-modpath textures 48 | if(!VREF(texture_set, ogl.external)) glBlendFunc(GL_ONE, GL_ZERO); 49 | } 50 | 51 | // modpath textures rendered in 3D should always be filtered 52 | if(vertextype != TLVERTEX && current_state.texture_set && VREF(texture_set, ogl.external)) current_state.texture_filter = true; 53 | 54 | // modpath textures in menu should always be filtered 55 | if(mode == MODE_MENU && current_state.texture_set && VREF(texture_set, ogl.external)) current_state.texture_filter = true; 56 | 57 | // some modpath textures have filtering forced on 58 | if(current_state.texture_set && VREF(texture_set, ogl.gl_set->force_filter) && VREF(texture_set, ogl.external)) current_state.texture_filter = true; 59 | 60 | // some modpath textures have z-sort forced on 61 | if(current_state.texture_set && VREF(texture_set, ogl.gl_set->force_zsort) && VREF(texture_set, ogl.external)) defer = true; 62 | 63 | // z-sort by default in menu and condor battle, unnecessary sorting will be 64 | // avoided by defer logic 65 | if(mode == MODE_MENU) defer = true; 66 | if(mode == MODE_CONDOR) defer = true; 67 | 68 | if(ff8) 69 | { 70 | // fix cerberus line effect 71 | if(mode == MODE_SWIRL && primitivetype == GL_LINES && vertices[0].color.color == 0 && vertices[1].color.color == 0xFFFF0000 && vertexcount <= 64) 72 | { 73 | uint i, j; 74 | 75 | gl_set_blend_func(2); 76 | 77 | for(i = 0; i < vertexcount; i += 2) 78 | { 79 | uint color1 = vertices[i].color.color; 80 | uint color2 = vertices[i + 1].color.color; 81 | float z = vertices[i]._.z; 82 | double x = vertices[i]._.x; 83 | double factor = (double)internal_size_x / (double)width; 84 | double inv_factor = 0.5 / factor; 85 | uint new_count = ((uint)(4 * factor)) * 2; 86 | struct nvertex *_vertices = driver_malloc(new_count * sizeof(*_vertices)); 87 | word *_indices = driver_malloc(new_count * sizeof(*_indices)); 88 | 89 | for(j = 0; j < new_count; j += 2) 90 | { 91 | _vertices[j]._.x = (float)x; 92 | _vertices[j]._.y = vertices[i]._.y; 93 | _vertices[j]._.z = z; 94 | _vertices[j].color.w = 1.0f; 95 | _vertices[j].color.color = 0x80000000; 96 | 97 | _indices[j] = j; 98 | 99 | _vertices[j + 1]._.x = (float)x; 100 | _vertices[j + 1]._.y = vertices[i + 1]._.y; 101 | _vertices[j + 1]._.z = z; 102 | _vertices[j + 1].color.w = 1.0f; 103 | _vertices[j + 1].color.color = 0x8000FFFF; 104 | 105 | _indices[j + 1] = j + 1; 106 | 107 | x += inv_factor; 108 | } 109 | 110 | gl_draw_indexed_primitive(primitivetype, vertextype, _vertices, new_count, _indices, new_count, graphics_object, false, true); 111 | 112 | driver_free(_vertices); 113 | driver_free(_indices); 114 | } 115 | 116 | return true; 117 | } 118 | 119 | // fix FF8 battle swirl zoom effect 120 | if(*ff8_externals.swirl_texture1) 121 | { 122 | if((*ff8_externals.swirl_texture1)->hundred_data) 123 | { 124 | if(current_state.texture_set && current_state.texture_set == (*ff8_externals.swirl_texture1)->hundred_data->texture_set) 125 | { 126 | // normal battle swirl 127 | if(vertexcount == 4 && current_state.blend_mode == 1) 128 | { 129 | float offset = vertices[1]._.x - 640.0f; 130 | 131 | offset = (1.0f - cosf((offset / 160.0f) * (M_PI / 2.0f))) * 160.0f; 132 | 133 | vertices[0]._.x = offset; 134 | vertices[1]._.x = 640.0f + offset; 135 | vertices[2]._.x = offset; 136 | vertices[3]._.x = 640.0f + offset; 137 | 138 | vertices[0]._.y = 16.0f; 139 | vertices[1]._.y = 16.0f; 140 | vertices[2]._.y = 464.0f; 141 | vertices[3]._.y = 464.0f; 142 | 143 | vertices[0].color.color = 0xFF404040; 144 | vertices[1].color.color = 0xFF101010; 145 | vertices[2].color.color = 0xFF404040; 146 | vertices[3].color.color = 0xFF101010; 147 | } 148 | 149 | // boss swirl 150 | if(vertexcount == 16) 151 | { 152 | vertices[0]._.x = -vertices[4]._.x; 153 | vertices[1]._.x = 640.0f - (vertices[5]._.x - 640.0f); 154 | vertices[2]._.x = -vertices[6]._.x; 155 | vertices[3]._.x = 640.0f - (vertices[7]._.x - 640.0f); 156 | vertices[8]._.x = -vertices[12]._.x; 157 | vertices[9]._.x = 640.0f - (vertices[13]._.x - 640.0f); 158 | vertices[10]._.x = -vertices[14]._.x; 159 | vertices[11]._.x = 640.0f - (vertices[15]._.x - 640.0f); 160 | 161 | vertices[0]._.y = 16.0f - (vertices[8]._.y - 16.0f); 162 | vertices[1]._.y = 16.0f - (vertices[9]._.y - 16.0f); 163 | vertices[2]._.y = 464.0f - (vertices[10]._.y - 464.0f); 164 | vertices[3]._.y = 464.0f - (vertices[11]._.y - 464.0f); 165 | vertices[4]._.y = 16.0f - (vertices[12]._.y - 16.0f); 166 | vertices[5]._.y = 16.0f - (vertices[13]._.y - 16.0f); 167 | vertices[6]._.y = 464.0f - (vertices[14]._.y - 464.0f); 168 | vertices[7]._.y = 464.0f - (vertices[15]._.y - 464.0f); 169 | } 170 | } 171 | } 172 | } 173 | 174 | // fix FF8 battle swirl fade effect 175 | if(mode == MODE_SWIRL && primitivetype == GL_LINES && vertexcount == 896) 176 | { 177 | uint i; 178 | uint color1 = vertices[0].color.color; 179 | uint color2 = vertices[1].color.color; 180 | float z = vertices[0]._.z; 181 | double y = vertices[0]._.y; 182 | double factor = (double)internal_size_y / (double)height; 183 | double inv_factor = 0.5 / factor; 184 | uint new_count = ((uint)((vertexcount + 2) * factor)) * 2; 185 | struct nvertex *_vertices = driver_malloc(new_count * sizeof(*_vertices)); 186 | word *_indices = driver_malloc(new_count * sizeof(*_indices)); 187 | 188 | for(i = 0; i < new_count; i += 2) 189 | { 190 | uint xvert = ((uint)(i / factor) / 4) * 2 + 1; 191 | float x = vertices[min(xvert, 895)]._.x; 192 | 193 | _vertices[i]._.x = 0.0f; 194 | _vertices[i]._.y = (float)y; 195 | _vertices[i]._.z = z; 196 | _vertices[i].color.w = 1.0f; 197 | _vertices[i].color.color = color1; 198 | 199 | _indices[i] = i; 200 | 201 | _vertices[i + 1]._.x = x; 202 | _vertices[i + 1]._.y = (float)y; 203 | _vertices[i + 1]._.z = z; 204 | _vertices[i + 1].color.w = 1.0f; 205 | _vertices[i + 1].color.color = 0xFF000000; 206 | 207 | _indices[i + 1] = i + 1; 208 | 209 | y += inv_factor; 210 | } 211 | 212 | gl_draw_indexed_primitive(primitivetype, vertextype, _vertices, new_count, _indices, new_count, graphics_object, false, true); 213 | 214 | driver_free(_vertices); 215 | driver_free(_indices); 216 | 217 | return true; 218 | } 219 | } 220 | else 221 | { 222 | if(SAFE_GFXOBJ_CHECK(graphics_object, ff7_externals.menu_objects->buster_tex)) 223 | { 224 | // stretch main menu to fullscreen if it is a modpath texture 225 | if(VREF(texture_set, ogl.external) && vertexcount == 4) 226 | { 227 | vertices[0]._.x = 0.0f; 228 | vertices[0]._.y = 0.0f; 229 | vertices[0]._.z = 1.0f; 230 | vertices[1]._.x = 0.0f; 231 | vertices[1]._.y = (float)height; 232 | vertices[1]._.z = 1.0f; 233 | vertices[2]._.x = (float)width; 234 | vertices[2]._.y = 0.0f; 235 | vertices[2]._.z = 1.0f; 236 | vertices[3]._.x = (float)width; 237 | vertices[3]._.y = (float)height; 238 | vertices[3]._.z = 1.0f; 239 | vertices[0].u = 0.0f; 240 | vertices[0].v = 0.0f; 241 | vertices[1].u = 0.0f; 242 | vertices[1].v = 1.0f; 243 | vertices[2].u = 1.0f; 244 | vertices[2].v = 0.0f; 245 | vertices[3].u = 1.0f; 246 | vertices[3].v = 1.0f; 247 | } 248 | } 249 | 250 | if(current_state.texture_set && VREF(texture_set, tex_header)) 251 | { 252 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 253 | 254 | if((uint)VREF(tex_header, file.pc_name) > 32) 255 | { 256 | // avoid filtering window borders 257 | if(!strnicmp(VREF(tex_header, file.pc_name), "menu/btl_win_c_", strlen("menu/btl_win_c_") - 1) && VREF(texture_set, palette_index) == 0) current_state.texture_filter = false; 258 | } 259 | } 260 | 261 | // z-sort select menu elements everywhere 262 | if(SAFE_GFXOBJ_CHECK(graphics_object, ff7_externals.menu_objects->menu_fade)) defer = true; 263 | if(SAFE_GFXOBJ_CHECK(graphics_object, ff7_externals.menu_objects->blend_window_bg)) defer = true; 264 | 265 | if(mode == MODE_BATTLE && vertextype == TLVERTEX) 266 | { 267 | // z-sort all obvious GUI elements in battle 268 | if(!(current_state.viewport[2] == 640 && (current_state.viewport[3] == 332 || current_state.viewport[3] == 480)) || vertexcount == 4) defer = true; 269 | } 270 | } 271 | 272 | if(defer && fancy_transparency) return gl_defer_draw(primitivetype, vertextype, vertices, vertexcount, indices, count, clip, mipmap); 273 | 274 | return false; 275 | } 276 | -------------------------------------------------------------------------------- /gl/texture.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * gl/texture.c - support functions for loading/using OpenGL textures 21 | */ 22 | 23 | #include 24 | 25 | #include "../types.h" 26 | #include "../log.h" 27 | #include "../gl.h" 28 | #include "../common.h" 29 | #include "../macro.h" 30 | #include "../saveload.h" 31 | 32 | // check to make sure we can actually load a given texture 33 | void gl_check_texture_dimensions(uint width, uint height, char *source) 34 | { 35 | if(width > max_texture_size || height > max_texture_size) error("texture dimensions exceed max texture size, will not be able to load %s\n", source); 36 | } 37 | 38 | // create a blank OpenGL texture 39 | GLuint gl_create_empty_texture() 40 | { 41 | GLuint texture; 42 | 43 | glGenTextures(1, &texture); 44 | 45 | glBindTexture(GL_TEXTURE_2D, texture); 46 | 47 | return texture; 48 | } 49 | 50 | // create a simple texture from pixel data, if the size parameter is used it 51 | // will be treated as a compressed texture 52 | GLuint gl_create_texture(void *data, uint width, uint height, uint format, uint internalformat, uint size, bool generate_mipmaps) 53 | { 54 | GLuint texture = gl_create_empty_texture(); 55 | 56 | if(size) glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, format, width, height, 0, size, data); 57 | else glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_UNSIGNED_BYTE, data); 58 | 59 | if(generate_mipmaps) glGenerateMipmapEXT(GL_TEXTURE_2D); 60 | 61 | return texture; 62 | } 63 | 64 | /* 65 | * Pixel Buffer Object (PBO) support 66 | * Only one pixel buffer can be outstanding at a time, normal workflow is to 67 | * request a new pixel buffer, fill it with data and commit it ASAP. 68 | * Uses a circular buffer of PBOs to encourage lazy uploading of data 69 | */ 70 | 71 | #define PBO_RING_SIZE 32 72 | 73 | uint pbo_ring[PBO_RING_SIZE]; 74 | uint pbo_index; 75 | bool commited; 76 | 77 | void gl_init_pbo_ring() 78 | { 79 | glGenBuffers(PBO_RING_SIZE, pbo_ring); 80 | pbo_index = 0; 81 | commited = true; 82 | } 83 | 84 | void *gl_get_pixel_buffer(uint size) 85 | { 86 | void *ret; 87 | 88 | if(!use_pbo) return driver_malloc(size); 89 | 90 | if(!commited) error("PBO not commited\n"); 91 | 92 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_ring[pbo_index]); 93 | glBufferData(GL_PIXEL_UNPACK_BUFFER, size, 0, GL_STREAM_DRAW); 94 | ret = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); 95 | 96 | commited = false; 97 | 98 | pbo_index = (pbo_index + 1) % PBO_RING_SIZE; 99 | 100 | return ret; 101 | } 102 | 103 | GLuint gl_commit_pixel_buffer_generic(void *data, uint width, uint height, uint format, uint internalformat, uint size, bool generate_mipmaps) 104 | { 105 | uint ret; 106 | 107 | if(!use_pbo) 108 | { 109 | ret = gl_create_texture(data, width, height, format, internalformat, size, generate_mipmaps); 110 | driver_free(data); 111 | return ret; 112 | } 113 | 114 | if(commited) error("PBO already commited\n"); 115 | 116 | glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 117 | 118 | ret = gl_create_texture(0, width, height, format, internalformat, size, generate_mipmaps); 119 | 120 | glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 121 | 122 | commited = true; 123 | 124 | return ret; 125 | } 126 | 127 | GLuint gl_commit_pixel_buffer(void *data, uint width, uint height, uint format, bool generate_mipmaps) 128 | { 129 | return gl_commit_pixel_buffer_generic(data, width, height, format, GL_RGBA8, 0, generate_mipmaps); 130 | } 131 | 132 | GLuint gl_compress_pixel_buffer(void *data, uint width, uint height, uint format) 133 | { 134 | return gl_commit_pixel_buffer_generic(data, width, height, format, GL_COMPRESSED_RGBA, 0, true); 135 | } 136 | 137 | GLuint gl_commit_compressed_buffer(void *data, uint width, uint height, uint format, uint size) 138 | { 139 | return gl_commit_pixel_buffer_generic(data, width, height, format, 0, size, true); 140 | } 141 | 142 | // apply OpenGL texture for a certain palette in a texture set, possibly 143 | // replacing an existing texture which will then be unloaded 144 | void gl_replace_texture(struct texture_set *texture_set, uint palette_index, uint new_texture) 145 | { 146 | VOBJ(texture_set, texture_set, texture_set); 147 | 148 | if(VREF(texture_set, texturehandle[palette_index]) != 0) 149 | { 150 | if(VREF(texture_set, ogl.external)) glitch("oops, may have messed up an external texture\n"); 151 | glDeleteTextures(1, VREFP(texture_set, texturehandle[palette_index])); 152 | } 153 | 154 | VRASS(texture_set, texturehandle[palette_index], new_texture); 155 | } 156 | 157 | // upload texture for a texture set from raw pixel data 158 | void gl_upload_texture(struct texture_set *texture_set, uint palette_index, void *image_data, uint format) 159 | { 160 | GLuint texture; 161 | uint w, h; 162 | VOBJ(texture_set, texture_set, texture_set); 163 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 164 | 165 | if(VREF(texture_set, ogl.external)) 166 | { 167 | w = VREF(texture_set, ogl.width); 168 | h = VREF(texture_set, ogl.height); 169 | } 170 | else 171 | { 172 | w = VREF(tex_header, version) == FB_TEX_VERSION ? VREF(tex_header, fb_tex.w) : VREF(tex_header, tex_format.width); 173 | h = VREF(tex_header, version) == FB_TEX_VERSION ? VREF(tex_header, fb_tex.h) : VREF(tex_header, tex_format.height); 174 | } 175 | 176 | gl_check_texture_dimensions(w, h, "unknown"); 177 | 178 | texture = gl_commit_pixel_buffer(image_data, w, h, format, false); 179 | 180 | gl_replace_texture(texture_set, palette_index, texture); 181 | } 182 | 183 | // prepare texture set for rendering 184 | void gl_bind_texture_set(struct texture_set *_texture_set) 185 | { 186 | VOBJ(texture_set, texture_set, _texture_set); 187 | 188 | if(VPTR(texture_set)) 189 | { 190 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 191 | 192 | gl_set_texture(VREF(texture_set, texturehandle[VREF(tex_header, palette_index)])); 193 | 194 | if(VREF(tex_header, version) == FB_TEX_VERSION) current_state.fb_texture = true; 195 | else current_state.fb_texture = false; 196 | 197 | ext_cache_access(VPTR(texture_set)); 198 | } 199 | else gl_set_texture(0); 200 | 201 | current_state.texture_set = VPTR(texture_set); 202 | } 203 | 204 | // prepare an OpenGL texture for rendering, passing zero to this function will 205 | // disable texturing entirely 206 | void gl_set_texture(GLuint texture) 207 | { 208 | if(trace_all) trace("set texture %i\n", texture); 209 | 210 | if(texture) 211 | { 212 | glBindTexture(GL_TEXTURE_2D, texture); 213 | glUniform1i(glGetUniformLocation(current_program, "texture"), 1); 214 | } 215 | else 216 | { 217 | glUniform1i(glGetUniformLocation(current_program, "texture"), 0); 218 | } 219 | 220 | current_state.texture_handle = texture; 221 | current_state.texture_set = 0; 222 | } 223 | -------------------------------------------------------------------------------- /globals.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * globals.h - global variables 21 | */ 22 | 23 | #ifndef _GLOBALS_H_ 24 | #define _GLOBALS_H_ 25 | 26 | #include 27 | 28 | #include "types.h" 29 | #include "ff7.h" 30 | #include "ff8.h" 31 | 32 | extern uint version; 33 | 34 | #define BASEDIR_LENGTH 512 35 | extern char basedir[BASEDIR_LENGTH]; 36 | 37 | extern uint width; 38 | extern uint height; 39 | extern uint x_offset; 40 | extern uint y_offset; 41 | extern uint output_size_x; 42 | extern uint output_size_y; 43 | extern bool indirect_rendering; 44 | 45 | extern struct texture_format *texture_format; 46 | 47 | extern struct ff7_externals ff7_externals; 48 | extern struct ff8_externals ff8_externals; 49 | extern struct common_externals common_externals; 50 | extern struct driver_stats stats; 51 | 52 | extern char popup_msg[]; 53 | extern uint popup_ttl; 54 | extern uint popup_color; 55 | 56 | extern HWND hwnd; 57 | 58 | extern unsigned char font_map[]; 59 | extern struct game_mode modes[]; 60 | extern uint num_modes; 61 | 62 | extern uint text_colors[]; 63 | 64 | extern bool ff8; 65 | 66 | extern uint frame_counter; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * log.c - logging routines for writing to app.log 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "types.h" 28 | #include "globals.h" 29 | #include "log.h" 30 | 31 | FILE *app_log; 32 | 33 | void open_applog(char *path) 34 | { 35 | app_log = fopen(path, "w"); 36 | 37 | if(!app_log) MessageBoxA(hwnd, "Failed to open log file", "Error", 0); 38 | } 39 | 40 | void plugin_trace(const char *fmt, ...) 41 | { 42 | va_list args; 43 | char tmp_str[1024]; 44 | 45 | va_start(args, fmt); 46 | 47 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 48 | 49 | trace("%s", tmp_str); 50 | } 51 | 52 | void plugin_info(const char *fmt, ...) 53 | { 54 | va_list args; 55 | char tmp_str[1024]; 56 | 57 | va_start(args, fmt); 58 | 59 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 60 | 61 | info("%s", tmp_str); 62 | } 63 | 64 | void plugin_glitch(const char *fmt, ...) 65 | { 66 | va_list args; 67 | char tmp_str[1024]; 68 | 69 | va_start(args, fmt); 70 | 71 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 72 | 73 | glitch("%s", tmp_str); 74 | } 75 | 76 | void plugin_error(const char *fmt, ...) 77 | { 78 | va_list args; 79 | char tmp_str[1024]; 80 | 81 | va_start(args, fmt); 82 | 83 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 84 | 85 | error("%s", tmp_str); 86 | } 87 | 88 | void debug_print(const char *str) 89 | { 90 | char tmp_str[1024]; 91 | 92 | sprintf(tmp_str, "[%08i] %s", frame_counter, str); 93 | 94 | fwrite(tmp_str, 1, strlen(tmp_str), app_log); 95 | fflush(app_log); 96 | } 97 | 98 | // filter out some less useful spammy messages 99 | const char ff7_filter[] = "SET VOLUME "; 100 | const char ff8_filter[] = "Patch "; 101 | 102 | void external_debug_print(const char *str) 103 | { 104 | if(!ff8 && !strncmp(str, ff7_filter, sizeof(ff7_filter) - 1)) return; 105 | if(ff8 && !strncmp(str, ff8_filter, sizeof(ff8_filter) - 1)) return; 106 | 107 | if(show_applog) debug_print(str); 108 | 109 | if(ff7_popup) 110 | { 111 | strcpy(popup_msg, str); 112 | popup_ttl = POPUP_TTL_MAX; 113 | popup_color = text_colors[TEXTCOLOR_GRAY]; 114 | } 115 | } 116 | 117 | void external_debug_print2(const char *fmt, ...) 118 | { 119 | va_list args; 120 | char tmp_str[1024]; 121 | 122 | va_start(args, fmt); 123 | 124 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 125 | external_debug_print(tmp_str); 126 | } 127 | 128 | #define POPUP_LOG_LENGTH 128 129 | 130 | void debug_printf(const char *prefix, bool popup, uint color, const char *fmt, ...) 131 | { 132 | va_list args; 133 | char tmp_str[1024]; 134 | char tmp_str2[1024]; 135 | 136 | va_start(args, fmt); 137 | 138 | vsnprintf(tmp_str, sizeof(tmp_str), fmt, args); 139 | _snprintf(tmp_str2, sizeof(tmp_str2), "%s: %s", prefix, tmp_str); 140 | debug_print(tmp_str2); 141 | 142 | if(popup) 143 | { 144 | #ifdef RELEASE 145 | static char *popup_log[POPUP_LOG_LENGTH]; 146 | static uint popup_log_index = 0; 147 | uint i; 148 | 149 | for(i = 0; i < POPUP_LOG_LENGTH; i++) 150 | { 151 | if(popup_log[i] && !strcmp(popup_log[i], tmp_str2)) return; 152 | } 153 | 154 | if(popup_log[popup_log_index]) free(popup_log[popup_log_index]); 155 | 156 | popup_log[popup_log_index] = strdup(tmp_str2); 157 | 158 | popup_log_index = (popup_log_index + 1) % POPUP_LOG_LENGTH; 159 | #endif 160 | 161 | strcpy(popup_msg, tmp_str2); 162 | popup_ttl = POPUP_TTL_MAX; 163 | popup_color = color; 164 | } 165 | } 166 | 167 | void windows_error(uint error) 168 | { 169 | char tmp_str[200]; 170 | 171 | if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, error == 0 ? GetLastError() : error, 0, tmp_str, sizeof(tmp_str), 0)) debug_print(tmp_str); 172 | } 173 | 174 | void gl_error() 175 | { 176 | GLenum ret = glGetError(); 177 | 178 | while(ret != GL_NO_ERROR) 179 | { 180 | switch(ret) 181 | { 182 | case GL_INVALID_ENUM: 183 | error("GL_INVALID_ENUM\n"); 184 | break; 185 | case GL_INVALID_VALUE: 186 | error("GL_INVALID_VALUE\n"); 187 | break; 188 | case GL_INVALID_OPERATION: 189 | error("GL_INVALID_OPERATION\n"); 190 | break; 191 | case GL_STACK_OVERFLOW: 192 | error("GL_STACK_OVERFLOW\n"); 193 | break; 194 | case GL_STACK_UNDERFLOW: 195 | error("GL_STACK_UNDERFLOW\n"); 196 | break; 197 | case GL_OUT_OF_MEMORY: 198 | error("GL_OUT_OF_MEMORY\n"); 199 | break; 200 | } 201 | 202 | ret = glGetError(); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * log.h - logging routines 21 | */ 22 | 23 | #ifndef _LOG_H_ 24 | #define _LOG_H_ 25 | 26 | #include "types.h" 27 | #include "cfg.h" 28 | #include "common.h" 29 | #include "globals.h" 30 | 31 | #define glitch_once(x, ...) { static bool glitch_ ## __LINE__ = false; if(!glitch_ ## __LINE__) { glitch(x, __VA_ARGS__); glitch_ ## __LINE__ = true; } } 32 | #define unexpected_once(x, ...) { static bool unexpected_ ## __LINE__ = false; if(!unexpected_ ## __LINE__) { unexpected(x, __VA_ARGS__); unexpected_ ## __LINE__ = true; } } 33 | 34 | #define error(x, ...) debug_printf("ERROR", true, text_colors[TEXTCOLOR_RED], (x), __VA_ARGS__) 35 | #define info(x, ...) debug_printf("INFO", info_popup, text_colors[TEXTCOLOR_WHITE], (x), __VA_ARGS__) 36 | #define dump(x, ...) debug_printf("DUMP", false, text_colors[TEXTCOLOR_PINK], (x), __VA_ARGS__) 37 | #ifndef RELEASE 38 | #define trace(x, ...) debug_printf("TRACE", true, text_colors[TEXTCOLOR_GREEN], (x), __VA_ARGS__) 39 | #else 40 | #define trace(x, ...) 41 | #endif 42 | #define glitch(x, ...) debug_printf("GLITCH", true, text_colors[TEXTCOLOR_YELLOW], (x), __VA_ARGS__) 43 | #define unexpected(x, ...) debug_printf("UNEXPECTED", true, text_colors[TEXTCOLOR_LIGHT_BLUE], (x), __VA_ARGS__) 44 | 45 | void open_applog(char *path); 46 | 47 | void plugin_trace(const char *fmt, ...); 48 | void plugin_info(const char *fmt, ...); 49 | void plugin_glitch(const char *fmt, ...); 50 | void plugin_error(const char *fmt, ...); 51 | 52 | void external_debug_print(const char *str); 53 | void external_debug_print2(const char *fmt, ...); 54 | 55 | void debug_printf(const char *, bool, uint, const char *, ...); 56 | 57 | void windows_error(uint error); 58 | void gl_error(); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /macro.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * macro.h - useful macros 21 | */ 22 | 23 | #ifndef _MACRO_H_ 24 | #define _MACRO_H_ 25 | 26 | #include "globals.h" 27 | #include "cfg.h" 28 | 29 | #define LIST_FOR_EACH(X, Y) for((X) = (Y)->head; (X); (X) = (X)->next) 30 | 31 | /* 32 | * Versioned structure macros, used to access FF7 and FF8 data in a portable 33 | * way. Allows massive, relatively straightforward code reuse between the two 34 | * games. Watch out for block statements and using expressions with side 35 | * effects! These macros can have unintended effects if you're not careful. 36 | */ 37 | 38 | /* 39 | * VOBJ - Define a versioned object, structure must have FF7 and FF8 variants 40 | * named ff7_ and ff8_ respectively. 41 | * X - type name 42 | * Y - object name 43 | * Z - initial value 44 | */ 45 | #define VOBJ(X,Y,Z) struct ff7_ ## X *ff7_ ## Y = ff8 ? 0 : (void *)(Z); struct ff8_ ## X *ff8_ ## Y = ff8 ? (void *)(Z) : 0 46 | 47 | /* 48 | * VPTR - Access the raw pointer contained in an object. 49 | * X - object 50 | */ 51 | #define VPTR(X) (ff8 ? (void *)ff8_ ## X : (void *)ff7_ ## X) 52 | 53 | /* 54 | * VASS - Assign a new pointer to an object. 55 | * X - object 56 | * Y - new value 57 | */ 58 | #define VASS(X,Y) { if(ff8) ff8_ ## X = (void *)(Y); else ff7_ ## X = (void *)(Y); } 59 | 60 | /* 61 | * VREF - Retrieve the value of a member of an object. 62 | * X - object 63 | * Y - member name (member must be identical in both versions of the structure!) 64 | */ 65 | #define VREF(X,Y) (ff8 ? ff8_ ## X->Y : ff7_ ## X->Y) 66 | 67 | /* 68 | * VREFP - Create a pointer to a member. 69 | * X - object 70 | * Y - member name (member must be identical in both versions of the structure!) 71 | */ 72 | #define VREFP(X,Y) (ff8 ? &(ff8_ ## X->Y) : &(ff7_ ## X->Y)) 73 | 74 | /* 75 | * VRASS - Assign a value to a member. 76 | * X - object 77 | * Y - member name (member must be identical in both versions of the structure!) 78 | */ 79 | #define VRASS(X,Y,Z) { if(ff8) ff8_ ## X->Y = (Z); else ff7_ ## X->Y = (Z); } 80 | 81 | /* 82 | * UNSAFE_VREF - Retrieve the value of a member of an object WITHOUT type safety. 83 | * X - object 84 | * Y - member name (types can be different in the different versions) 85 | */ 86 | #define UNSAFE_VREF(X,Y) (ff8 ? (void *)ff8_ ## X->Y : (void *)ff7_ ## X->Y) 87 | 88 | // convert a coordinate from game coordinates to internal rendering coordinates 89 | #define INT_COORD_X(X) (((X) * internal_size_x) / width) 90 | #define INT_COORD_Y(X) (((X) * internal_size_y) / height) 91 | 92 | // convert a coordinate from internal rendering coordinates to output coordinates 93 | #define OUT_COORD_X(X) (((X) * output_size_x) / internal_size_x) 94 | #define OUT_COORD_Y(X) (((X) * output_size_y) / internal_size_y) 95 | 96 | #define BGRA_R(x) (x >> 16 & 0xFF) 97 | #define BGRA_G(x) (x >> 8 & 0xFF) 98 | #define BGRA_B(x) (x & 0xFF) 99 | #define BGRA_A(x) (x >> 24 & 0xFF) 100 | 101 | #define BIT(x) (1 << x) 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /matrix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * matrix.c - basic matrix and vector math 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "matrix.h" 27 | #include "math.h" 28 | #include "log.h" 29 | 30 | void add_vector(struct point3d *a, struct point3d *b, struct point3d *dest) 31 | { 32 | dest->x = a->x + b->x; 33 | dest->y = a->y + b->y; 34 | dest->z = a->z + b->z; 35 | } 36 | 37 | void subtract_vector(struct point3d *a, struct point3d *b, struct point3d *dest) 38 | { 39 | dest->x = a->x - b->x; 40 | dest->y = a->y - b->y; 41 | dest->z = a->z - b->z; 42 | } 43 | 44 | void multiply_vector(struct point3d *vector, float scalar, struct point3d *dest) 45 | { 46 | dest->x = vector->x * scalar; 47 | dest->y = vector->y * scalar; 48 | dest->z = vector->z * scalar; 49 | } 50 | 51 | void divide_vector(struct point3d *vector, float scalar, struct point3d *dest) 52 | { 53 | dest->x = vector->x / scalar; 54 | dest->y = vector->y / scalar; 55 | dest->z = vector->z / scalar; 56 | } 57 | 58 | float vector_length(struct point3d *vector) 59 | { 60 | return sqrtf(vector->x * vector->x + vector->y * vector->y + vector->z * vector->z); 61 | } 62 | 63 | void normalize_vector(struct point3d *vector) 64 | { 65 | float length = vector_length(vector); 66 | 67 | divide_vector(vector, length, vector); 68 | } 69 | 70 | float dot_product(struct point3d *a, struct point3d *b) 71 | { 72 | return a->x * b->x + a->y * b->y + a->z * b->z; 73 | } 74 | 75 | void cross_product(struct point3d *a, struct point3d *b, struct point3d *dest) 76 | { 77 | dest->x = a->y * b->z - a->z * b->y; 78 | dest->y = a->z * b->x - a->x * b->z; 79 | dest->z = a->x * b->y - a->y * b->x; 80 | } 81 | 82 | void transform_point(struct matrix *matrix, struct point3d *point, struct point3d *dest) 83 | { 84 | dest->x = matrix->_11 * point->x + matrix->_21 * point->y + matrix->_31 * point->z + matrix->_41; 85 | dest->y = matrix->_12 * point->x + matrix->_22 * point->y + matrix->_32 * point->z + matrix->_42; 86 | dest->z = matrix->_13 * point->x + matrix->_23 * point->y + matrix->_33 * point->z + matrix->_43; 87 | } 88 | 89 | void transform_point_w(struct matrix *matrix, struct point3d *point, struct point4d *dest) 90 | { 91 | dest->x = matrix->_11 * point->x + matrix->_21 * point->y + matrix->_31 * point->z + matrix->_41; 92 | dest->y = matrix->_12 * point->x + matrix->_22 * point->y + matrix->_32 * point->z + matrix->_42; 93 | dest->z = matrix->_13 * point->x + matrix->_23 * point->y + matrix->_33 * point->z + matrix->_43; 94 | dest->w = matrix->_14 * point->x + matrix->_24 * point->y + matrix->_34 * point->z + matrix->_44; 95 | } 96 | 97 | void transform_point4d(struct matrix *matrix, struct point4d *point, struct point4d *dest) 98 | { 99 | dest->x = matrix->_11 * point->x + matrix->_21 * point->y + matrix->_31 * point->z + matrix->_41 * point->w; 100 | dest->y = matrix->_12 * point->x + matrix->_22 * point->y + matrix->_32 * point->z + matrix->_42 * point->w; 101 | dest->z = matrix->_13 * point->x + matrix->_23 * point->y + matrix->_33 * point->z + matrix->_43 * point->w; 102 | dest->w = matrix->_14 * point->x + matrix->_24 * point->y + matrix->_34 * point->z + matrix->_44 * point->w; 103 | } 104 | 105 | void transpose_matrix(struct matrix *matrix, struct matrix *dest) 106 | { 107 | dest->_11 = matrix->_11; 108 | dest->_12 = matrix->_21; 109 | dest->_13 = matrix->_31; 110 | dest->_14 = matrix->_41; 111 | dest->_21 = matrix->_12; 112 | dest->_22 = matrix->_22; 113 | dest->_23 = matrix->_32; 114 | dest->_24 = matrix->_42; 115 | dest->_31 = matrix->_13; 116 | dest->_32 = matrix->_23; 117 | dest->_33 = matrix->_33; 118 | dest->_34 = matrix->_43; 119 | dest->_41 = matrix->_14; 120 | dest->_42 = matrix->_24; 121 | dest->_43 = matrix->_34; 122 | dest->_44 = matrix->_44; 123 | } 124 | 125 | void multiply_matrix(struct matrix *a, struct matrix *b, struct matrix *dest) 126 | { 127 | 128 | #define MMUL(I, J, N) a->m[I - 1][N - 1] * b->m[N - 1][J - 1] 129 | #define MMUL1(I, J) dest->m[I - 1][J - 1] = MMUL(I, J, 1) + MMUL(I, J, 2) + MMUL(I, J, 3) + MMUL(I, J, 4) 130 | #define MMULROW(I) MMUL1(I, 1); MMUL1(I, 2); MMUL1(I, 3); MMUL1(I, 4) 131 | 132 | MMULROW(1); 133 | MMULROW(2); 134 | MMULROW(3); 135 | MMULROW(4); 136 | } 137 | 138 | void multiply_matrix_unary(struct matrix *a, struct matrix *b) 139 | { 140 | struct matrix tmp; 141 | 142 | memcpy(&tmp, a, sizeof(tmp)); 143 | multiply_matrix(&tmp, b, a); 144 | } 145 | 146 | void identity_matrix(struct matrix *matrix) 147 | { 148 | matrix->_11 = 1.0f; 149 | matrix->_12 = 0.0f; 150 | matrix->_13 = 0.0f; 151 | matrix->_14 = 0.0f; 152 | matrix->_21 = 0.0f; 153 | matrix->_22 = 1.0f; 154 | matrix->_23 = 0.0f; 155 | matrix->_24 = 0.0f; 156 | matrix->_31 = 0.0f; 157 | matrix->_32 = 0.0f; 158 | matrix->_33 = 1.0f; 159 | matrix->_34 = 0.0f; 160 | matrix->_41 = 0.0f; 161 | matrix->_42 = 0.0f; 162 | matrix->_43 = 0.0f; 163 | matrix->_44 = 1.0f; 164 | } 165 | 166 | void uniform_scaling_matrix(float scale, struct matrix *matrix) 167 | { 168 | identity_matrix(matrix); 169 | 170 | matrix->_11 = scale; 171 | matrix->_22 = scale; 172 | matrix->_33 = scale; 173 | } 174 | 175 | void scaling_matrix(struct point3d *scale, struct matrix *matrix) 176 | { 177 | identity_matrix(matrix); 178 | 179 | matrix->_11 = scale->x; 180 | matrix->_22 = scale->y; 181 | matrix->_33 = scale->z; 182 | } 183 | 184 | void rotation_matrix_x(float angle, struct matrix *matrix) 185 | { 186 | identity_matrix(matrix); 187 | 188 | matrix->_22 = cosf(angle); 189 | matrix->_23 = sinf(angle); 190 | matrix->_32 = -sinf(angle); 191 | matrix->_33 = cosf(angle); 192 | } 193 | 194 | void rotation_matrix_y(float angle, struct matrix *matrix) 195 | { 196 | identity_matrix(matrix); 197 | 198 | matrix->_11 = cosf(angle); 199 | matrix->_13 = -sinf(angle); 200 | matrix->_31 = sinf(angle); 201 | matrix->_33 = cosf(angle); 202 | } 203 | 204 | void rotation_matrix_z(float angle, struct matrix *matrix) 205 | { 206 | identity_matrix(matrix); 207 | 208 | matrix->_11 = cosf(angle); 209 | matrix->_12 = sinf(angle); 210 | matrix->_21 = -sinf(angle); 211 | matrix->_22 = cosf(angle); 212 | } 213 | 214 | void rotate_matrix_x(float angle, struct matrix *matrix) 215 | { 216 | struct matrix tmp; 217 | 218 | rotation_matrix_x(angle, &tmp); 219 | multiply_matrix_unary(matrix, &tmp); 220 | } 221 | 222 | void rotate_matrix_y(float angle, struct matrix *matrix) 223 | { 224 | struct matrix tmp; 225 | 226 | rotation_matrix_y(angle, &tmp); 227 | multiply_matrix_unary(matrix, &tmp); 228 | } 229 | 230 | void rotate_matrix_z(float angle, struct matrix *matrix) 231 | { 232 | struct matrix tmp; 233 | 234 | rotation_matrix_z(angle, &tmp); 235 | multiply_matrix_unary(matrix, &tmp); 236 | } 237 | 238 | float determinant_3x3(struct matrix *m) 239 | { 240 | return m->_11 * m->_22 * m->_33 + m->_12 * m->_23 * m->_31 + m->_13 * m->_21 * m->_32 - 241 | m->_11 * m->_23 * m->_32 - m->_12 * m->_21 * m->_33 - m->_13 * m->_22 * m->_31; 242 | } 243 | 244 | void inverse_matrix(struct matrix *matrix, struct matrix *dest) 245 | { 246 | float det = determinant_3x3(matrix); 247 | 248 | if((det >= 0.99 && det <= 1.01) || (det <= -0.99 && det >= -1.01)) 249 | { 250 | struct point3d translation; 251 | 252 | transpose_matrix(matrix, dest); 253 | dest->_14 = matrix->_14; 254 | dest->_24 = matrix->_24; 255 | dest->_34 = matrix->_34; 256 | dest->_44 = matrix->_44; 257 | 258 | transform_point(dest, (struct point3d *)&matrix->_41, &translation); 259 | 260 | dest->_41 = -translation.x; 261 | dest->_42 = -translation.y; 262 | dest->_43 = -translation.z; 263 | } 264 | else glitch_once("Non-uniform scaling: %f\n", det); 265 | } 266 | -------------------------------------------------------------------------------- /matrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * matrix.h - matrix & vector definitions 21 | */ 22 | 23 | #ifndef _MATRIX_H_ 24 | #define _MATRIX_H_ 25 | 26 | #define M_PI 3.14159265358979323846f 27 | #define DEG2RAD(X) ((X) * (M_PI/180.0f)) 28 | 29 | struct matrix 30 | { 31 | union 32 | { 33 | struct 34 | { 35 | float _11; 36 | float _12; 37 | float _13; 38 | float _14; 39 | float _21; 40 | float _22; 41 | float _23; 42 | float _24; 43 | float _31; 44 | float _32; 45 | float _33; 46 | float _34; 47 | float _41; 48 | float _42; 49 | float _43; 50 | float _44; 51 | }; 52 | 53 | float m[4][4]; 54 | }; 55 | }; 56 | 57 | struct point3d 58 | { 59 | float x; 60 | float y; 61 | float z; 62 | }; 63 | 64 | struct point4d 65 | { 66 | float x; 67 | float y; 68 | float z; 69 | float w; 70 | }; 71 | 72 | void add_vector(struct point3d *a, struct point3d *b, struct point3d *dest); 73 | void subtract_vector(struct point3d *a, struct point3d *b, struct point3d *dest); 74 | void multiply_vector(struct point3d *vector, float scalar, struct point3d *dest); 75 | void divide_vector(struct point3d *vector, float scalar, struct point3d *dest); 76 | float vector_length(struct point3d *vector); 77 | void normalize_vector(struct point3d *vector); 78 | float dot_product(struct point3d *a, struct point3d *b); 79 | void cross_product(struct point3d *a, struct point3d *b, struct point3d *dest); 80 | void transform_point(struct matrix *matrix, struct point3d *point, struct point3d *dest); 81 | void transform_point_w(struct matrix *matrix, struct point3d *point, struct point4d *dest); 82 | void transform_point4d(struct matrix *matrix, struct point4d *point, struct point4d *dest); 83 | void transpose_matrix(struct matrix *matrix, struct matrix *dest); 84 | void multiply_matrix(struct matrix *a, struct matrix *b, struct matrix *dest); 85 | void multiply_matrix_unary(struct matrix *a, struct matrix *b); 86 | void identity_matrix(struct matrix *matrix); 87 | void uniform_scaling_matrix(float scale, struct matrix *matrix); 88 | void scaling_matrix(struct point3d *scale, struct matrix *matrix); 89 | void rotation_matrix_x(float angle, struct matrix *matrix); 90 | void rotation_matrix_y(float angle, struct matrix *matrix); 91 | void rotation_matrix_z(float angle, struct matrix *matrix); 92 | void rotate_matrix_x(float angle, struct matrix *matrix); 93 | void rotate_matrix_y(float angle, struct matrix *matrix); 94 | void rotate_matrix_z(float angle, struct matrix *matrix); 95 | void inverse_matrix(struct matrix *matrix, struct matrix *dest); 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /movies.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * movies.c - replacements routines for FMV player 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "types.h" 27 | #include "gl.h" 28 | #include "movies.h" 29 | #include "patch.h" 30 | #include "globals.h" 31 | #include "log.h" 32 | #include "common.h" 33 | #include "cfg.h" 34 | 35 | HMODULE movie_lib; 36 | 37 | struct movie_plugin *movies; 38 | 39 | void movie_init() 40 | { 41 | if(!ff8) 42 | { 43 | replace_function(common_externals.prepare_movie, ff7_prepare_movie); 44 | replace_function(common_externals.release_movie_objects, ff7_release_movie_objects); 45 | replace_function(common_externals.start_movie, ff7_start_movie); 46 | replace_function(common_externals.update_movie_sample, ff7_update_movie_sample); 47 | replace_function(common_externals.stop_movie, ff7_stop_movie); 48 | replace_function(common_externals.get_movie_frame, ff7_get_movie_frame); 49 | } 50 | else 51 | { 52 | replace_function(common_externals.prepare_movie, ff8_prepare_movie); 53 | replace_function(common_externals.release_movie_objects, ff8_release_movie_objects); 54 | replace_function(common_externals.start_movie, ff8_start_movie); 55 | replace_function(common_externals.update_movie_sample, ff8_update_movie_sample); 56 | replace_function(ff8_externals.draw_movie_frame, draw_current_frame); 57 | replace_function(common_externals.stop_movie, ff8_stop_movie); 58 | replace_function(common_externals.get_movie_frame, ff8_get_movie_frame); 59 | } 60 | 61 | movie_lib = LoadLibraryA(movie_plugin); 62 | 63 | movies = driver_calloc(1, sizeof(*movies)); 64 | 65 | movies->movie_init = (void *)GetProcAddress(movie_lib, "movie_init"); 66 | movies->prepare_movie = (void *)GetProcAddress(movie_lib, "prepare_movie"); 67 | movies->release_movie_objects = (void *)GetProcAddress(movie_lib, "release_movie_objects"); 68 | movies->update_movie_sample = (void *)GetProcAddress(movie_lib, "update_movie_sample"); 69 | movies->loop = (void *)GetProcAddress(movie_lib, "loop"); 70 | movies->stop_movie = (void *)GetProcAddress(movie_lib, "stop_movie"); 71 | movies->get_movie_frame = (void *)GetProcAddress(movie_lib, "get_movie_frame"); 72 | 73 | if(!(movies->movie_init && 74 | movies->prepare_movie && 75 | movies->release_movie_objects && 76 | movies->update_movie_sample && 77 | movies->loop && 78 | movies->stop_movie && 79 | movies->get_movie_frame)) 80 | { 81 | MessageBoxA(hwnd, "Error loading movie plugin, cannot continue.", "Error", 0); 82 | error("could not load movie plugin: %s\n", movie_plugin); 83 | exit(1); 84 | } 85 | 86 | movies->movie_init(plugin_trace, plugin_info, plugin_glitch, plugin_error, gl_draw_movie_quad_bgra, gl_draw_movie_quad_yuv, common_externals.directsound, skip_frames, movie_sync_debug); 87 | } 88 | 89 | bool ff7_prepare_movie(char *name, uint loop, struct dddevice **dddevice, uint dd2interface) 90 | { 91 | if(trace_all || trace_movies) trace("prepare_movie %s\n", name); 92 | 93 | ff7_externals.movie_object->loop = loop; 94 | ff7_externals.movie_sub_415231(name); 95 | 96 | ff7_externals.movie_object->field_1F8 = 1; 97 | ff7_externals.movie_object->is_playing = 0; 98 | ff7_externals.movie_object->movie_end = 0; 99 | ff7_externals.movie_object->global_movie_flag = 0; 100 | ff7_externals.movie_object->field_E0 = !((struct ff7_game_obj *)common_externals.get_game_object())->field_968; 101 | 102 | movies->prepare_movie(name); 103 | 104 | ff7_externals.movie_object->global_movie_flag = 1; 105 | 106 | return true; 107 | } 108 | 109 | void ff7_release_movie_objects() 110 | { 111 | if(trace_all || trace_movies) trace("release_movie_objects\n"); 112 | 113 | ff7_stop_movie(); 114 | 115 | movies->release_movie_objects(); 116 | 117 | ff7_externals.movie_object->global_movie_flag = 0; 118 | } 119 | 120 | bool ff7_start_movie() 121 | { 122 | if(trace_all || trace_movies) trace("start_movie\n"); 123 | 124 | if(ff7_externals.movie_object->is_playing) return true; 125 | 126 | ff7_externals.movie_object->is_playing = 1; 127 | 128 | return ff7_update_movie_sample(0); 129 | } 130 | 131 | bool ff7_stop_movie() 132 | { 133 | if(trace_all || trace_movies) trace("stop_movie\n"); 134 | 135 | if(ff7_externals.movie_object->is_playing) 136 | { 137 | ff7_externals.movie_object->is_playing = 0; 138 | ff7_externals.movie_object->movie_end = 0; 139 | 140 | movies->stop_movie(); 141 | } 142 | 143 | return true; 144 | } 145 | 146 | bool ff7_update_movie_sample(LPDIRECTDRAWSURFACE surface) 147 | { 148 | bool movie_end; 149 | 150 | ff7_externals.movie_object->movie_end = 0; 151 | 152 | if(!ff7_externals.movie_object->is_playing) return false; 153 | 154 | retry: 155 | movie_end = !movies->update_movie_sample(); 156 | 157 | if(movie_end) 158 | { 159 | if(trace_all || trace_movies) trace("movie end\n"); 160 | if(ff7_externals.movie_object->loop) 161 | { 162 | movies->loop(); 163 | goto retry; 164 | } 165 | 166 | ff7_externals.movie_object->movie_end = 1; 167 | return true; 168 | } 169 | 170 | return true; 171 | } 172 | 173 | void draw_current_frame() 174 | { 175 | movies->draw_current_frame(); 176 | } 177 | 178 | uint ff7_get_movie_frame() 179 | { 180 | if(!ff7_externals.movie_object->is_playing) return 0; 181 | 182 | return movies->get_movie_frame(); 183 | } 184 | 185 | uint ff8_movie_frames; 186 | 187 | void ff8_prepare_movie(unsigned char disc, unsigned char movie) 188 | { 189 | char fmvName[512]; 190 | char camName[512]; 191 | FILE *camFile; 192 | uint camOffset = 0; 193 | 194 | _snprintf(fmvName, sizeof(fmvName), "%s/data/movies/disc%02i_%02ih.avi", basedir, disc, movie); 195 | _snprintf(camName, sizeof(camName), "%s/data/movies/disc%02i_%02i.cam", basedir, disc, movie); 196 | 197 | if(trace_all || trace_movies) trace("prepare_movie %s\n", fmvName); 198 | 199 | if(disc != 4) 200 | { 201 | camFile = fopen(camName, "rb"); 202 | 203 | if(!camFile) 204 | { 205 | error("could not load camera data from %s\n", camName); 206 | return; 207 | } 208 | 209 | while(!feof(camFile) && !ferror(camFile)) 210 | { 211 | uint res = fread(&ff8_externals.movie_object->camdata_buffer[camOffset], 1, 4096, camFile); 212 | 213 | if(res > 0) camOffset += res; 214 | } 215 | 216 | ff8_externals.movie_object->movie_intro_pak = false; 217 | } 218 | else ff8_externals.movie_object->movie_intro_pak = true; 219 | 220 | ff8_externals.movie_object->camdata_start = (struct camdata *)(&ff8_externals.movie_object->camdata_buffer[8]); 221 | ff8_externals.movie_object->camdata_pointer = ff8_externals.movie_object->camdata_start; 222 | 223 | ff8_externals.movie_object->movie_frame = 0; 224 | 225 | ff8_movie_frames = movies->prepare_movie(fmvName); 226 | } 227 | 228 | void ff8_release_movie_objects() 229 | { 230 | if(trace_all || trace_movies) trace("release_movie_objects\n"); 231 | 232 | movies->release_movie_objects(); 233 | } 234 | 235 | void ff8_start_movie() 236 | { 237 | if(trace_all || trace_movies) trace("start_movie\n"); 238 | 239 | if(ff8_externals.movie_object->movie_intro_pak) ff8_externals.movie_object->field_2 = ff8_movie_frames; 240 | else 241 | { 242 | ff8_externals.movie_object->field_2 = ((word *)ff8_externals.movie_object->camdata_buffer)[3]; 243 | trace("%i frames\n", ff8_externals.movie_object->field_2); 244 | } 245 | 246 | ff8_externals.movie_object->field_4C4B0 = 0; 247 | 248 | *ff8_externals.enable_framelimiter = false; 249 | 250 | ff8_update_movie_sample(); 251 | 252 | ff8_externals.movie_object->movie_is_playing = true; 253 | } 254 | 255 | void ff8_stop_movie() 256 | { 257 | if(trace_all || trace_movies) trace("stop_movie\n"); 258 | 259 | movies->stop_movie(); 260 | 261 | ff8_externals.movie_object->movie_is_playing = false; 262 | 263 | ff8_externals.movie_object->field_4C4AC = 0; 264 | ff8_externals.movie_object->field_4C4B0 = 0; 265 | 266 | *ff8_externals.enable_framelimiter = true; 267 | } 268 | 269 | void ff8_update_movie_sample() 270 | { 271 | if(trace_all || trace_movies) trace("update_movie_sample\n"); 272 | 273 | if(!movies->update_movie_sample()) 274 | { 275 | if(ff8_externals.movie_object->movie_intro_pak) ff8_stop_movie(); 276 | else ff8_externals.sub_5304B0(); 277 | } 278 | 279 | ff8_externals.movie_object->movie_frame = movies->get_movie_frame(); 280 | 281 | if(ff8_externals.movie_object->camdata_pointer->field_28 & 0x8) *ff8_externals.byte_1CE4907 = 0; 282 | if(ff8_externals.movie_object->camdata_pointer->field_28 & 0x10) *ff8_externals.byte_1CE4907 = 1; 283 | if(ff8_externals.movie_object->camdata_pointer->field_28 & 0x20) 284 | { 285 | *ff8_externals.byte_1CE4901 = 1; 286 | ff8_externals.movie_object->field_4C4B0 = 1; 287 | } 288 | else 289 | { 290 | *ff8_externals.byte_1CE4901 = 0; 291 | ff8_externals.movie_object->field_4C4B0 = 0; 292 | } 293 | 294 | if(ff8_externals.movie_object->camdata_pointer->field_28 & 0x1) 295 | { 296 | *ff8_externals.byte_1CE4901 = 1; 297 | ff8_externals.movie_object->field_4C4B0 = 1; 298 | } 299 | 300 | *ff8_externals.byte_1CE490D = ff8_externals.movie_object->camdata_pointer->field_28 & 0x40; 301 | 302 | if(ff8_externals.movie_object->movie_frame > ff8_externals.movie_object->field_2) 303 | { 304 | if(ff8_externals.movie_object->movie_intro_pak) ff8_stop_movie(); 305 | else ff8_externals.sub_5304B0(); 306 | 307 | return; 308 | } 309 | 310 | ff8_externals.movie_object->camdata_pointer = &ff8_externals.movie_object->camdata_start[ff8_externals.movie_object->movie_frame]; 311 | } 312 | 313 | uint ff8_get_movie_frame() 314 | { 315 | if(trace_all || trace_movies) trace("get_movie_frame\n"); 316 | 317 | return ff8_externals.movie_object->movie_frame; 318 | } 319 | -------------------------------------------------------------------------------- /movies.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * movies.h - FMV player definitions 21 | */ 22 | 23 | #ifndef _MOVIES_H_ 24 | #define _MOVIES_H_ 25 | 26 | #include "types.h" 27 | 28 | struct movie_plugin 29 | { 30 | void (*movie_init)(void *, void *, void *, void *, void *, void *, void **, bool, bool); 31 | uint (*prepare_movie)(char *); 32 | void (*release_movie_objects)(); 33 | bool (*update_movie_sample)(); 34 | void (*draw_current_frame)(); 35 | void (*loop)(); 36 | void (*stop_movie)(); 37 | uint (*get_movie_frame)(); 38 | }; 39 | 40 | void movie_init(); 41 | bool ff7_prepare_movie(char *, uint, struct dddevice **, uint); 42 | void ff7_release_movie_objects(); 43 | bool ff7_start_movie(); 44 | bool ff7_update_movie_sample(LPDIRECTDRAWSURFACE); 45 | bool ff7_stop_movie(); 46 | uint ff7_get_movie_frame(); 47 | void draw_current_frame(); 48 | void ff8_prepare_movie(uint disc, uint movie); 49 | void ff8_release_movie_objects(); 50 | void ff8_start_movie(); 51 | void ff8_update_movie_sample(); 52 | void ff8_stop_movie(); 53 | uint ff8_get_movie_frame(); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /music.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * music.c - replacements routines for music player 21 | */ 22 | 23 | #include 24 | 25 | #include "music.h" 26 | #include "types.h" 27 | #include "globals.h" 28 | #include "cfg.h" 29 | #include "log.h" 30 | #include "patch.h" 31 | 32 | HMODULE music_lib; 33 | 34 | struct music_plugin *music; 35 | 36 | void music_init() 37 | { 38 | music_lib = LoadLibraryA(music_plugin); 39 | 40 | music = driver_calloc(1, sizeof(*music)); 41 | 42 | music->music_init = (void *)GetProcAddress(music_lib, "music_init"); 43 | music->play_music = (void *)GetProcAddress(music_lib, "play_music"); 44 | music->cross_fade_music = (void *)GetProcAddress(music_lib, "cross_fade_music"); 45 | music->pause_music = (void *)GetProcAddress(music_lib, "pause_music"); 46 | music->resume_music = (void *)GetProcAddress(music_lib, "resume_music"); 47 | music->stop_music = (void *)GetProcAddress(music_lib, "stop_music"); 48 | music->music_status = (void *)GetProcAddress(music_lib, "music_status"); 49 | music->set_master_music_volume = (void *)GetProcAddress(music_lib, "set_master_music_volume"); 50 | music->set_music_volume = (void *)GetProcAddress(music_lib, "set_music_volume"); 51 | music->set_music_volume_trans = (void *)GetProcAddress(music_lib, "set_music_volume_trans"); 52 | music->set_music_tempo = (void *)GetProcAddress(music_lib, "set_music_tempo"); 53 | 54 | if(!(music->music_init && 55 | music->play_music && 56 | music->cross_fade_music && 57 | music->pause_music && 58 | music->resume_music && 59 | music->stop_music && 60 | music->music_status && 61 | music->set_master_music_volume && 62 | music->set_music_volume && 63 | music->set_music_volume_trans && 64 | music->set_music_tempo)) 65 | { 66 | MessageBoxA(hwnd, "Error loading music plugin.", "Error", 0); 67 | error("could not load music plugin: %s\n", music_plugin); 68 | return; 69 | } 70 | 71 | replace_function(common_externals.midi_init, midi_init); 72 | replace_function(common_externals.play_midi, play_midi); 73 | replace_function(common_externals.cross_fade_midi, cross_fade_midi); 74 | replace_function(common_externals.pause_midi, pause_midi); 75 | replace_function(common_externals.restart_midi, restart_midi); 76 | replace_function(common_externals.stop_midi, stop_midi); 77 | replace_function(common_externals.midi_status, midi_status); 78 | replace_function(common_externals.set_master_midi_volume, set_master_midi_volume); 79 | replace_function(common_externals.set_midi_volume, set_midi_volume); 80 | replace_function(common_externals.set_midi_volume_trans, set_midi_volume_trans); 81 | replace_function(common_externals.set_midi_tempo, set_midi_tempo); 82 | 83 | music->music_init(plugin_trace, plugin_info, plugin_glitch, plugin_error, common_externals.directsound, basedir); 84 | } 85 | 86 | bool midi_init(uint unknown) 87 | { 88 | // without this there will be no volume control for music in the config menu 89 | *ff7_externals.midi_volume_control = true; 90 | 91 | // enable fade function 92 | *ff7_externals.midi_initialized = true; 93 | 94 | return true; 95 | } 96 | 97 | void play_midi(uint midi) 98 | { 99 | music->play_music(common_externals.get_midi_name(midi), midi); 100 | } 101 | 102 | void cross_fade_midi(uint midi, uint time) 103 | { 104 | music->cross_fade_music(common_externals.get_midi_name(midi), midi, time); 105 | } 106 | 107 | void pause_midi() 108 | { 109 | music->pause_music(); 110 | } 111 | 112 | void restart_midi() 113 | { 114 | music->resume_music(); 115 | } 116 | 117 | void stop_midi() 118 | { 119 | if(music->stop_music) music->stop_music(); 120 | } 121 | 122 | bool midi_status() 123 | { 124 | return music->music_status(); 125 | } 126 | 127 | void set_master_midi_volume(uint volume) 128 | { 129 | music->set_master_music_volume(volume); 130 | } 131 | 132 | void set_midi_volume(uint volume) 133 | { 134 | music->set_music_volume(volume); 135 | } 136 | 137 | void set_midi_volume_trans(uint volume, uint step) 138 | { 139 | music->set_music_volume_trans(volume, step); 140 | } 141 | 142 | void set_midi_tempo(unsigned char tempo) 143 | { 144 | music->set_music_tempo(tempo); 145 | } 146 | -------------------------------------------------------------------------------- /music.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * music.h - music player definitions 21 | */ 22 | 23 | #ifndef _MUSIC_H_ 24 | #define _MUSIC_H_ 25 | 26 | #include "types.h" 27 | 28 | struct music_plugin 29 | { 30 | void (*music_init)(void *, void *, void *, void *, void **, const char *); 31 | void (*play_music)(char *, uint); 32 | bool (*cross_fade_music)(char *, uint, uint); 33 | void (*pause_music)(); 34 | void (*resume_music)(); 35 | void (*stop_music)(); 36 | bool (*music_status)(); 37 | void (*set_master_music_volume)(uint); 38 | void (*set_music_volume)(uint); 39 | void (*set_music_volume_trans)(uint, uint); 40 | void (*set_music_tempo)(unsigned char); 41 | }; 42 | 43 | void music_init(); 44 | bool midi_init(uint unknown); 45 | void cleanup_midi(); 46 | void play_midi(uint midi); 47 | void cross_fade_midi(uint midi, uint time); 48 | void pause_midi(); 49 | void restart_midi(); 50 | void stop_midi(); 51 | bool midi_status(); 52 | void set_master_midi_volume(uint volume); 53 | void set_midi_volume(uint volume); 54 | void set_midi_volume_trans(uint volume, uint step); 55 | void set_midi_tempo(unsigned char tempo); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /patch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * patch.c - helper functions for runtime code patching 21 | */ 22 | 23 | #include 24 | 25 | #include "types.h" 26 | 27 | uint replace_counter = 0; 28 | uint replaced_functions[512 * 3]; 29 | 30 | uint replace_function(uint offset, void *func) 31 | { 32 | uint dummy; 33 | 34 | VirtualProtect((void *)offset, 5, PAGE_EXECUTE_READWRITE, &dummy); 35 | 36 | replaced_functions[replace_counter++] = *(unsigned char *)offset; 37 | replaced_functions[replace_counter++] = *(uint *)(offset + 1); 38 | replaced_functions[replace_counter++] = offset; 39 | 40 | *(unsigned char *)offset = 0xE9; 41 | *(uint *)(offset + 1) = ((uint)func - offset) - 5; 42 | 43 | return replace_counter - 3; 44 | } 45 | 46 | void unreplace_function(uint func) 47 | { 48 | uint offset = replaced_functions[func + 2]; 49 | uint dummy; 50 | 51 | VirtualProtect((void *)offset, 5, PAGE_EXECUTE_READWRITE, &dummy); 52 | *(uint *)(offset + 1) = replaced_functions[func + 1]; 53 | *(unsigned char *)offset = replaced_functions[func]; 54 | } 55 | 56 | void unreplace_functions() 57 | { 58 | while(replace_counter > 0) 59 | { 60 | uint offset = replaced_functions[--replace_counter]; 61 | uint dummy; 62 | 63 | VirtualProtect((void *)offset, 5, PAGE_EXECUTE_READWRITE, &dummy); 64 | *(uint *)(offset + 1) = replaced_functions[--replace_counter]; 65 | *(unsigned char *)offset = replaced_functions[--replace_counter]; 66 | } 67 | } 68 | 69 | void replace_call(uint offset, void *func) 70 | { 71 | uint dummy; 72 | 73 | VirtualProtect((void *)offset, 5, PAGE_EXECUTE_READWRITE, &dummy); 74 | 75 | *(uint *)(offset + 1) = ((uint)func - offset) - 5; 76 | } 77 | 78 | uint get_relative_call(uint base, uint offset) 79 | { 80 | return base + *((uint *)(base + offset + 1)) + offset + 5; 81 | } 82 | 83 | uint get_absolute_value(uint base, uint offset) 84 | { 85 | return *((uint *)(base + offset)); 86 | } 87 | 88 | void patch_code_byte(uint offset, unsigned char r) 89 | { 90 | uint dummy; 91 | 92 | VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); 93 | 94 | *(unsigned char *)offset = r; 95 | } 96 | 97 | void patch_code_word(uint offset, word r) 98 | { 99 | uint dummy; 100 | 101 | VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); 102 | 103 | *(word *)offset = r; 104 | } 105 | 106 | void patch_code_uint(uint offset, uint r) 107 | { 108 | uint dummy; 109 | 110 | VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); 111 | 112 | *(uint *)offset = r; 113 | } 114 | 115 | void patch_code_float(uint offset, float r) 116 | { 117 | uint dummy; 118 | 119 | VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); 120 | 121 | *(float *)offset = r; 122 | } 123 | 124 | void patch_code_double(uint offset, double r) 125 | { 126 | uint dummy; 127 | 128 | VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); 129 | 130 | *(double *)offset = r; 131 | } 132 | 133 | void memcpy_code(uint offset, void *data, uint size) 134 | { 135 | uint dummy; 136 | 137 | VirtualProtect((void *)offset, size, PAGE_EXECUTE_READWRITE, &dummy); 138 | 139 | memcpy((void *)offset, data, size); 140 | } 141 | 142 | void memset_code(uint offset, uint val, uint size) 143 | { 144 | uint dummy; 145 | 146 | VirtualProtect((void *)offset, size, PAGE_EXECUTE_READWRITE, &dummy); 147 | 148 | memset((void *)offset, val, size); 149 | } 150 | -------------------------------------------------------------------------------- /patch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * patch.h - helper functions for runtime code patching 21 | */ 22 | 23 | #ifndef _PATCH_H_ 24 | #define _PATCH_H_ 25 | 26 | #include "types.h" 27 | #include "globals.h" 28 | #include "log.h" 29 | 30 | uint replace_function(uint offset, void *func); 31 | void unreplace_function(uint func); 32 | void unreplace_functions(); 33 | 34 | void replace_call(uint offset, void *func); 35 | 36 | uint get_relative_call(uint base, uint offset); 37 | uint get_absolute_value(uint base, uint offset); 38 | void patch_code_byte(uint offset, unsigned char r); 39 | void patch_code_word(uint offset, word r); 40 | void patch_code_uint(uint offset, uint r); 41 | void patch_code_float(uint offset, float r); 42 | void patch_code_double(uint offset, double r); 43 | void memcpy_code(uint offset, void *data, uint size); 44 | void memset_code(uint offset, uint val, uint size); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /png.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * png.c - load/save routines for PNG images 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "types.h" 29 | #include "log.h" 30 | #include "globals.h" 31 | #include "gl.h" 32 | 33 | void _png_error(png_structp png_ptr, const char *error) 34 | { 35 | error("libpng error: %s\n", error); 36 | } 37 | 38 | void _png_warning(png_structp png_ptr, const char *warning) 39 | { 40 | error("libpng warning: %s\n", warning); 41 | } 42 | 43 | bool write_png(char *filename, uint width, uint height, char *data) 44 | { 45 | uint y; 46 | png_byte **rowptrs; 47 | FILE *f; 48 | png_infop info_ptr; 49 | png_structp png_ptr; 50 | 51 | if(fopen_s(&f, filename, "wb")) 52 | { 53 | error("couldn't open file %s for writing: %s", filename, _strerror(NULL)); 54 | return false; 55 | } 56 | 57 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0, _png_error, _png_warning); 58 | 59 | if(!png_ptr) 60 | { 61 | fclose(f); 62 | return false; 63 | } 64 | 65 | info_ptr = png_create_info_struct(png_ptr); 66 | 67 | if(!info_ptr) 68 | { 69 | png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 70 | fclose(f); 71 | return false; 72 | } 73 | 74 | if(setjmp(png_ptr->jmpbuf)) 75 | { 76 | png_destroy_write_struct(&png_ptr, &info_ptr); 77 | fclose(f); 78 | return false; 79 | } 80 | 81 | png_init_io(png_ptr, f); 82 | 83 | png_set_compression_level(png_ptr, Z_BEST_SPEED); 84 | 85 | png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 86 | 87 | rowptrs = driver_malloc(height * 4); 88 | 89 | for(y = 0; y < height; y++) rowptrs[y] = &data[y * width * 4]; 90 | 91 | png_set_rows(png_ptr, info_ptr, rowptrs); 92 | 93 | png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); 94 | 95 | png_destroy_write_struct(&png_ptr, &info_ptr); 96 | 97 | driver_free(rowptrs); 98 | 99 | fclose(f); 100 | 101 | return true; 102 | } 103 | 104 | uint *read_png(char *filename, uint *_width, uint *_height) 105 | { 106 | png_bytepp rowptrs; 107 | FILE *f; 108 | png_infop info_ptr; 109 | png_structp png_ptr; 110 | uint width; 111 | uint height; 112 | uint *data; 113 | uint y; 114 | uint color_type; 115 | 116 | if(fopen_s(&f, filename, "rb")) return 0; 117 | 118 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0, _png_error, _png_warning); 119 | 120 | if(!png_ptr) 121 | { 122 | fclose(f); 123 | return 0; 124 | } 125 | 126 | info_ptr = png_create_info_struct(png_ptr); 127 | 128 | if(!info_ptr) 129 | { 130 | png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); 131 | fclose(f); 132 | return 0; 133 | } 134 | 135 | if(setjmp(png_ptr->jmpbuf)) 136 | { 137 | png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); 138 | fclose(f); 139 | return 0; 140 | } 141 | 142 | png_init_io(png_ptr, f); 143 | 144 | png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); 145 | 146 | if(png_get_bit_depth(png_ptr, info_ptr) != 8) 147 | { 148 | error("invalid bitdepth\n"); 149 | return 0; 150 | } 151 | 152 | color_type = png_get_color_type(png_ptr, info_ptr); 153 | 154 | if(color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA) 155 | { 156 | error("invalid color type\n"); 157 | return 0; 158 | } 159 | 160 | rowptrs = png_get_rows(png_ptr, info_ptr); 161 | 162 | width = png_get_image_width(png_ptr, info_ptr); 163 | *_width = width; 164 | height = png_get_image_height(png_ptr, info_ptr); 165 | *_height = height; 166 | 167 | data = gl_get_pixel_buffer(width * height * 4); 168 | 169 | if(color_type == PNG_COLOR_TYPE_RGB) 170 | { 171 | uint x; 172 | 173 | for(y = 0; y < height; y++) 174 | { 175 | uint o = (uint)rowptrs[y]; 176 | 177 | for(x = 0; x < width; x++) 178 | { 179 | uint b = (*(unsigned char *)o++); 180 | uint g = (*(unsigned char *)o++); 181 | uint r = (*(unsigned char *)o++); 182 | 183 | data[y * width + x] = b | g << 8 | r << 16 | 0xFF << 24; 184 | } 185 | } 186 | } 187 | 188 | else for(y = 0; y < height; y++) memcpy(&data[y * width], rowptrs[y], width * 4); 189 | 190 | png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); 191 | 192 | fclose(f); 193 | 194 | return data; 195 | } 196 | -------------------------------------------------------------------------------- /png.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * png.h - libpng interface for reading/writing png files 21 | */ 22 | 23 | #ifndef _PNG_H_ 24 | #define _PNG_H_ 25 | 26 | bool write_png(char *filename, uint width, uint height, char *data); 27 | uint *read_png(char *filename, uint *_width, uint *_height); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /saveload.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * saveload.c - load/save routines for modpath texture replacements 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "types.h" 29 | #include "globals.h" 30 | #include "log.h" 31 | #include "gl.h" 32 | #include "cfg.h" 33 | #include "compile_cfg.h" 34 | #include "png.h" 35 | #include "ctx.h" 36 | #include "macro.h" 37 | 38 | void make_path(char *name) 39 | { 40 | char *next = name; 41 | 42 | while((next = strchr(next, '/'))) 43 | { 44 | char tmp[128]; 45 | 46 | while(next[0] == '/') next++; 47 | 48 | strncpy(tmp, name, next - name); 49 | tmp[next - name] = 0; 50 | 51 | mkdir(tmp); 52 | } 53 | } 54 | 55 | bool save_texture(void *data, uint width, uint height, uint palette_index, char *name) 56 | { 57 | char filename[sizeof(basedir) + 1024]; 58 | struct stat dummy; 59 | 60 | _snprintf(filename, sizeof(filename), "%s/mods/%s/%s_%02i.png", basedir, mod_path, name, palette_index); 61 | 62 | make_path(filename); 63 | 64 | if(stat(filename, &dummy)) return write_png(filename, width, height, data); 65 | else return true; 66 | } 67 | 68 | struct ext_cache_data 69 | { 70 | uint texture; 71 | uint size; 72 | }; 73 | 74 | struct ext_cache_entry 75 | { 76 | char *name; 77 | uint palette_index; 78 | uint references; 79 | time_t last_access; 80 | struct ext_cache_data data; 81 | }; 82 | 83 | #define EXT_CACHE_ENTRIES 512 84 | 85 | // the texture cache can only hold a certain number of textures in memory 86 | // there is also a configurable hard limit on how much memory can be used by the cache 87 | // once it is full the texture with the oldest access time is evicted 88 | struct ext_cache_entry *ext_cache[EXT_CACHE_ENTRIES]; 89 | 90 | // retrieve a single entry from the texture cache 91 | struct ext_cache_data *ext_cache_get(char *name, uint palette_index, int refcount) 92 | { 93 | uint i; 94 | 95 | for(i = 0; i < EXT_CACHE_ENTRIES; i++) 96 | { 97 | if(!ext_cache[i]) continue; 98 | 99 | if(ext_cache[i]->palette_index != palette_index) continue; 100 | 101 | if(trace_all) trace("Comparing: %s (%s)\n", ext_cache[i]->name, name); 102 | 103 | if(!_stricmp(ext_cache[i]->name, name)) 104 | { 105 | if(trace_all) trace("Matched: %s\n", ext_cache[i]->name); 106 | 107 | if(refcount >= 0 || ext_cache[i]->references) ext_cache[i]->references += refcount; 108 | 109 | if(refcount >= 0) qpc_get_time(&ext_cache[i]->last_access); 110 | 111 | return &ext_cache[i]->data; 112 | } 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | // update the access time of a single entry in the texture cache 119 | void ext_cache_access(struct texture_set *texture_set) 120 | { 121 | VOBJ(texture_set, texture_set, texture_set); 122 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 123 | 124 | if(!VREF(texture_set, ogl.external)) return; 125 | if((uint)VREF(tex_header, file.pc_name) > 32) ext_cache_get(VREF(tex_header, file.pc_name), VREF(texture_set, palette_index), 0); 126 | } 127 | 128 | // remove a reference to an entry in the texture cache 129 | void ext_cache_release(struct texture_set *texture_set) 130 | { 131 | uint i; 132 | VOBJ(texture_set, texture_set, texture_set); 133 | VOBJ(tex_header, tex_header, VREF(texture_set, tex_header)); 134 | 135 | if(!VREF(texture_set, ogl.external)) return; 136 | if((uint)VREF(tex_header, file.pc_name) > 32) 137 | { 138 | for(i = 0; i < VREF(texture_set, ogl.gl_set->textures); i++) 139 | { 140 | if(VREF(texture_set, texturehandle[i])) 141 | { 142 | ext_cache_get(VREF(tex_header, file.pc_name), i, -1); 143 | } 144 | } 145 | } 146 | } 147 | 148 | // add a new entry to the texture cache 149 | struct ext_cache_data *ext_cache_put(char *name, uint palette_index) 150 | { 151 | uint i; 152 | time_t oldest_access_time; 153 | uint oldest_texture; 154 | 155 | if(stats.ext_cache_size < texture_cache_size * 1024 * 1024) 156 | { 157 | for(i = 0; i < EXT_CACHE_ENTRIES; i++) 158 | { 159 | if(!ext_cache[i]) 160 | { 161 | ext_cache[i] = driver_calloc(sizeof(*ext_cache[i]), 1); 162 | ext_cache[i]->name = driver_malloc(strlen(name) + 1); 163 | strcpy(ext_cache[i]->name, name); 164 | ext_cache[i]->palette_index = palette_index; 165 | 166 | ext_cache[i]->references = 1; 167 | 168 | qpc_get_time(&ext_cache[i]->last_access); 169 | 170 | return &ext_cache[i]->data; 171 | } 172 | } 173 | } 174 | 175 | // access time can't be higher than current time 176 | qpc_get_time(&oldest_access_time); 177 | oldest_texture = EXT_CACHE_ENTRIES; 178 | 179 | for(i = 0; i < EXT_CACHE_ENTRIES; i++) 180 | { 181 | if(!ext_cache[i]) continue; 182 | 183 | if(!ext_cache[i]->references && ext_cache[i]->last_access < oldest_access_time) 184 | { 185 | oldest_access_time = ext_cache[i]->last_access; 186 | oldest_texture = i; 187 | } 188 | } 189 | 190 | if(oldest_texture == EXT_CACHE_ENTRIES) 191 | { 192 | error("texture cache is full and nothing could be evicted!\n"); 193 | return 0; 194 | } 195 | 196 | glDeleteTextures(1, &ext_cache[oldest_texture]->data.texture); 197 | 198 | stats.ext_cache_size -= ext_cache[oldest_texture]->data.size; 199 | 200 | ext_cache[oldest_texture]->name = driver_realloc(ext_cache[oldest_texture]->name, strlen(name) + 1); 201 | strcpy(ext_cache[oldest_texture]->name, name); 202 | ext_cache[oldest_texture]->palette_index = palette_index; 203 | memset(&ext_cache[oldest_texture]->data, 0, sizeof(ext_cache[oldest_texture]->data)); 204 | 205 | qpc_get_time(&ext_cache[oldest_texture]->last_access); 206 | 207 | return &ext_cache[oldest_texture]->data; 208 | } 209 | 210 | uint load_texture_helper(char *png_name, char *ctx_name, uint *width, uint *height, bool use_compression) 211 | { 212 | uint ret; 213 | uint *data; 214 | 215 | if(!(use_compression && compress_textures) || !(ret = read_ctx(ctx_name, width, height))) 216 | { 217 | data = read_png(png_name, width, height); 218 | 219 | if(!data) return 0; 220 | 221 | gl_check_texture_dimensions(*width, *height, png_name); 222 | 223 | if((use_compression && compress_textures)) 224 | { 225 | ret = gl_compress_pixel_buffer(data, *width, *height, GL_BGRA); 226 | if(!write_ctx(ctx_name, *width, *height, ret)) 227 | { 228 | glDeleteTextures(1, &ret); 229 | data = read_png(png_name, width, height); 230 | ret = gl_commit_pixel_buffer(data, *width, *height, GL_BGRA, true); 231 | stats.ext_cache_size += (*width) * (*height) * 4; 232 | } 233 | } 234 | else 235 | { 236 | ret = gl_commit_pixel_buffer(data, *width, *height, GL_BGRA, true); 237 | stats.ext_cache_size += (*width) * (*height) * 4; 238 | } 239 | } 240 | 241 | return ret; 242 | } 243 | 244 | uint load_texture(char *name, uint palette_index, uint *width, uint *height, bool use_compression) 245 | { 246 | char png_name[sizeof(basedir) + 1024]; 247 | char ctx_name[sizeof(basedir) + 1024]; 248 | uint ret; 249 | struct ext_cache_data *cache_data; 250 | 251 | cache_data = ext_cache_get(name, palette_index, 1); 252 | 253 | if(cache_data && cache_data->texture) return cache_data->texture; 254 | 255 | _snprintf(png_name, sizeof(png_name), "%s/mods/%s/%s_%02i.png", basedir, mod_path, name, palette_index); 256 | _snprintf(ctx_name, sizeof(ctx_name), "%s/mods/%s/cache/%s_%02i.ctx", basedir, mod_path, name, palette_index); 257 | 258 | ret = load_texture_helper(png_name, ctx_name, width, height, use_compression); 259 | 260 | if(!ret) 261 | { 262 | if(palette_index != 0) 263 | { 264 | if(show_missing_textures) info("tried to load %s, falling back to palette 0\n", png_name, palette_index); 265 | return load_texture(name, 0, width, height, use_compression); 266 | } 267 | else 268 | { 269 | if(show_missing_textures) info("tried to load %s, failed\n", png_name); 270 | return 0; 271 | } 272 | } 273 | 274 | if(trace_all) trace("Created texture: %i\n", ret); 275 | 276 | if(!cache_data) cache_data = ext_cache_put(name, palette_index); 277 | 278 | if(cache_data) 279 | { 280 | cache_data->texture = ret; 281 | cache_data->size += (*width) * (*height) * 4; 282 | } 283 | 284 | return ret; 285 | } 286 | -------------------------------------------------------------------------------- /saveload.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * saveload.h - save/load routines for modpath textures 21 | */ 22 | 23 | #ifndef _SAVELOAD_H_ 24 | #define _SAVELOAD_H_ 25 | 26 | #include "types.h" 27 | 28 | bool save_texture(void *data, uint width, uint height, uint palette_index, char *name); 29 | 30 | uint load_texture(char *name, uint palette_index, uint *width, uint *height, bool use_compression); 31 | 32 | void ext_cache_access(struct texture_set *texture_set); 33 | void ext_cache_release(struct texture_set *texture_set); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ff7_opengl - Complete OpenGL replacement of the Direct3D renderer used in 3 | * the original ports of Final Fantasy VII and Final Fantasy VIII for the PC. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | /* 20 | * types.h - standard types and definitions used throughout the code 21 | */ 22 | 23 | #ifndef _TYPES_H_ 24 | #define _TYPES_H_ 25 | 26 | typedef unsigned short word; 27 | typedef unsigned int uint; 28 | typedef unsigned int bool; 29 | 30 | #define true 1 31 | #define false 0 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /vgmstream_music/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H_ 2 | #define _TYPES_H_ 3 | 4 | typedef unsigned short word; 5 | typedef unsigned int uint; 6 | typedef unsigned int bool; 7 | 8 | #define true 1 9 | #define false 0 10 | 11 | #endif 12 | --------------------------------------------------------------------------------