├── LICENSE.txt ├── README.md ├── archives ├── mednafen-0.9.47-emu4crt-A01-win64.zip ├── mednafen-0.9.47-emu4crt-A02-win64.zip ├── mednafen-0.9.48-emu4crt-A04-win64.zip ├── mednafen-0.9.48-emu4crt-A05-win64.zip ├── mednafen-0.9.48-emu4crt-A06-win32.zip ├── mednafen-0.9.48-emu4crt-A06-win64.zip ├── mednafen-0.9.48-emu4crt-A07-win32.zip ├── mednafen-0.9.48-emu4crt-A07-win64.zip ├── mednafen-1.21.0-UNSTABLE-emu4crt-A08-win32.zip ├── mednafen-1.21.0-UNSTABLE-emu4crt-A08-win64.zip ├── mednafen-1.22.1-emu4crt-A09-win32.zip ├── mednafen-1.22.1-emu4crt-A09-win64.zip ├── mednafen-1.23.0-UNSTABLE-emu4crt-A09-win32.zip ├── mednafen-1.23.0-UNSTABLE-emu4crt-A09-win64.zip ├── mednafen-1.24.0-UNSTABLE-emu4crt-A09-win32.zip ├── mednafen-1.24.0-UNSTABLE-emu4crt-A09-win64.zip ├── mednafen-1.24.0-UNSTABLE-emu4crt-A10-win32.zip ├── mednafen-1.24.0-UNSTABLE-emu4crt-A10-win64.zip ├── mednafen-1.24.1-emu4crt-A11-win32.zip ├── mednafen-1.24.1-emu4crt-A11-win64.zip ├── mednafen-1.24.1-emu4crt-A12-win32.zip ├── mednafen-1.24.1-emu4crt-A12-win64.zip ├── mednafen-1.24.2-emu4crt-A13-win32.zip ├── mednafen-1.24.2-emu4crt-A13-win64.zip ├── mednafen-1.24.3-emu4crt-A13-win32.zip ├── mednafen-1.24.3-emu4crt-A13-win64.zip ├── mednafen-1.26.0-UNSTABLE-emu4crt-A13-win32.zip └── mednafen-1.26.0-UNSTABLE-emu4crt-A13-win64.zip ├── mednafen-1.26.1-emu4crt-A13-win32.zip ├── mednafen-1.26.1-emu4crt-A13-win64.zip ├── patches ├── mednafen-1.21.0-UNSTABLE-emu4crt-A08.patch ├── mednafen-1.22.1-emu4crt-A09.patch ├── mednafen-1.23.0-UNSTABLE-emu4crt-A09.patch ├── mednafen-1.24.0-UNSTABLE-emu4crt-A09.patch ├── mednafen-1.24.0-UNSTABLE-emu4crt-A10.patch ├── mednafen-1.24.0-UNSTABLE-emu4crt-A11.patch ├── mednafen-1.24.1-emu4crt-A11.patch ├── mednafen-1.24.1-emu4crt-A12.patch ├── mednafen-1.24.2-emu4crt-A13.patch ├── mednafen-1.24.3-emu4crt-A13.patch └── mednafen-1.26.0-emu4crt-A13.patch └── resolutions ├── emu4crt_RESOLUTIONS_NATIVE.txt └── emu4crt_RESOLUTIONS_SUPER.txt /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **Mednafen 1.26.1 - emu4crt - A13** 2 | 3 | emu4crt is a Mednafen emulator mod intended to be used on a system connected to a CRT screen, typically a 15kHz TV or an arcade monitor. 4 | 5 | It brings "pixel-perfect" rendering by switching host resolution to match emulated system resolution. 6 | 7 | * Mednafen modules ported to emu4crt: 8 | * Sony Playstation 9 | * Sega Saturn (win64 only) 10 | * Nintendo NES/Famicon (snes & snes_faust) 11 | * Nintendo Super NES/Super Famicom 12 | * NEC PC Engine / PC Engine CD / SuperGrafx (pce & pce_fast) 13 | * NEC PC-FX 14 | * Sega Megadrive / Genesis 15 | * Sega Master System 16 | 17 | Many options, meaningless in a CRT screen usage, have been removed from Mednafen in provided emu4crt builds (shaders, etc.). 18 | 19 | * Requirements: 20 | * OS: Windows 32/64bits 21 | * Video display: OpenGL compatible (the only Mednafen tested renderer). 22 | 23 | emu4crt can be use in two modes: 24 | 25 | * `Native Resolution`: Same resolution as emulated system. 26 | More custom resolution are required (see below) 27 | Generates more resolution changes, which has side effects 28 | 29 | * `Super Resolution`: Requires only four 2560 pixel width resolutions. 30 | Avoid some resolution change during emulation 31 | 32 | ## Required resolutions 33 | 34 | ### `Native resolutions` 35 | 36 | * Columns: 37 | 38 | | |256|320|341|352|368|512|640|704| 39 | |:------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 40 | |NES* | X | | | | | | | | 41 | |SNES | X | | | | | X | | | 42 | |SATURN | | X | | X | | | X | X | 43 | |PSX | X | X | | | X | X | X | | 44 | |PCE** | X | X | | | | X | | | 45 | |PCFX** | X | | X | | | | | | 46 | |MD/SMS | X | X | | | | | | | 47 | 48 | * Lines, for each column: 49 | 50 | NTSC modes : 240 and 480 lines @ 60 Hz 51 | PAL modes: 288 and 576 lines @ 50 Hz 52 | 53 | __*__ -> 240 and 288 lines only 54 | 55 | __**__ -> NTSC modes only 56 | 57 | ### `Super Resolutions` 58 | 59 | 4 custom resolutions cover all needs for every emulated systems: 60 | 61 | | | Columns | Lines | Frequency | 62 | |:-----| :------: | :-------: | :---------: | 63 | | NTSC | 2560 | 240 | 60Hz | 64 | | | 2560 | 480 | 60Hz | 65 | | PAL | 2560 | 288 | 50Hz | 66 | | | 2560 | 576 | 50Hz | 67 | 68 | Custom resolutions can be added on Windows by using Calamity's CRT Emudriver (the best way!), Soft15Hz, Powerstrip, manufacturer drivers... 69 | 70 | For CRT Emudriver users: 71 | * emu4crt_NATIVE_RESOLUTIONS.txt contains all resolution informations to be added to VMMAKER's user_modes.ini. 72 | * emu4crt_RESOLUTIONS_SUPER.txt 73 | 74 | For testing pupose, emu4crt can be used with a standard PC screen and video drivers in window mode. 75 | 76 | ## Configuration & usage 77 | 78 | To enable resolution switch, use "video.resolution_switch" parameter in mednafen.cfg configuration file: 79 | 80 | * video.resolution_switch native -> to use native resolution mode 81 | * video.resolution_switch super -> to use super resolution mode 82 | * video.resolution_switch 0 -> to disable resolution switch [DEFAULT MODE] 83 | 84 | emu4crt.exe can be placed in an existing mednafen.exe directory, both can share the same configuration file and all ressource files (firmwares, savestates, etc.). 85 | 86 | ## Limits and known issues 87 | 88 | - The emulator does not deal with resolution refresh rate. So, to get a deterministic behavior, a resolution must only exist at the expected refresh rate (ie. no 320x240 @ 55Hz). 89 | 90 | - Using emu4crt, resolution switch is not seamless process as it is on a console or with some other emulators. At each resolution change, some sound and graphical glitches will occur. 91 | 92 | - Graphical glitches can be limited by using full black Windows desktop background and taskbar hidding. 93 | 94 | - Windows 7 seems quicker than Windows 10 to switch resolution, at least with CRT Emudriver. 95 | 96 | - Emulation logic is preserved, so, expected game compatibility is same as with the Mednafen official release. 97 | 98 | If any specific issue with emu4crt mod, of course, do not bother the Mednafen Team! 99 | 100 | Contact forum thread: 101 | http://forum.arcadecontrols.com/index.php/topic,155264.0.html 102 | 103 | ## Thanks 104 | 105 | The Mednafen Team (https://mednafen.github.io) for... Mednafen! 106 | 107 | CRT Emudriver's author, Calamity (http://geedorah.com/eiusdemmodi/forum/) 108 | 109 | ArcadeControls.com (www.arcadecontrols.com) 110 | 111 | No$psx author, Martin Korth for publishing PSX GPU documentation 112 | 113 | hotdog963al for his PSX core horizontal centering improvment 114 | -------------------------------------------------------------------------------- /archives/mednafen-0.9.47-emu4crt-A01-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.47-emu4crt-A01-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.47-emu4crt-A02-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.47-emu4crt-A02-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A04-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A04-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A05-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A05-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A06-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A06-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A06-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A06-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A07-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A07-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-0.9.48-emu4crt-A07-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-0.9.48-emu4crt-A07-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.21.0-UNSTABLE-emu4crt-A08-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.21.0-UNSTABLE-emu4crt-A08-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.21.0-UNSTABLE-emu4crt-A08-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.21.0-UNSTABLE-emu4crt-A08-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.22.1-emu4crt-A09-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.22.1-emu4crt-A09-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.22.1-emu4crt-A09-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.22.1-emu4crt-A09-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.23.0-UNSTABLE-emu4crt-A09-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.23.0-UNSTABLE-emu4crt-A09-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.23.0-UNSTABLE-emu4crt-A09-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.23.0-UNSTABLE-emu4crt-A09-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.0-UNSTABLE-emu4crt-A09-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.0-UNSTABLE-emu4crt-A09-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.0-UNSTABLE-emu4crt-A09-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.0-UNSTABLE-emu4crt-A09-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.0-UNSTABLE-emu4crt-A10-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.0-UNSTABLE-emu4crt-A10-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.0-UNSTABLE-emu4crt-A10-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.0-UNSTABLE-emu4crt-A10-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.1-emu4crt-A11-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.1-emu4crt-A11-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.1-emu4crt-A11-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.1-emu4crt-A11-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.1-emu4crt-A12-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.1-emu4crt-A12-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.1-emu4crt-A12-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.1-emu4crt-A12-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.2-emu4crt-A13-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.2-emu4crt-A13-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.2-emu4crt-A13-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.2-emu4crt-A13-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.3-emu4crt-A13-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.3-emu4crt-A13-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.24.3-emu4crt-A13-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.24.3-emu4crt-A13-win64.zip -------------------------------------------------------------------------------- /archives/mednafen-1.26.0-UNSTABLE-emu4crt-A13-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.26.0-UNSTABLE-emu4crt-A13-win32.zip -------------------------------------------------------------------------------- /archives/mednafen-1.26.0-UNSTABLE-emu4crt-A13-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/archives/mednafen-1.26.0-UNSTABLE-emu4crt-A13-win64.zip -------------------------------------------------------------------------------- /mednafen-1.26.1-emu4crt-A13-win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/mednafen-1.26.1-emu4crt-A13-win32.zip -------------------------------------------------------------------------------- /mednafen-1.26.1-emu4crt-A13-win64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emu4crt/files/0a29b9b2198f61323785c3cc8b510f651cbfc809/mednafen-1.26.1-emu4crt-A13-win64.zip -------------------------------------------------------------------------------- /patches/mednafen-1.21.0-UNSTABLE-emu4crt-A08.patch: -------------------------------------------------------------------------------- 1 | diff -Naur /mednafen/src/drivers/main.cpp /emu4crt/src/drivers/main.cpp 2 | --- /mednafen/src/drivers/main.cpp 2018-02-19 20:21:58.000000000 +0100 3 | +++ /emu4crt/src/drivers/main.cpp 2018-02-26 22:54:14.434722773 +0100 4 | @@ -1137,6 +1137,31 @@ 5 | { 6 | while(GameThreadRun) 7 | { 8 | + //SLK trap change resolution request 9 | + if(resolution_to_change) 10 | + { 11 | + if(use_native_resolution) 12 | + { 13 | + if((current_resolution_w != resolution_to_change_w) || (current_resolution_h != resolution_to_change_h)) 14 | + { 15 | + GT_ChangeVideoResolution(); 16 | + printf("MAIN - native resolution switched\n"); 17 | + } 18 | + else {printf("MAIN - resolution change bypassed\n");} 19 | + } 20 | + if(use_super_resolution) 21 | + { 22 | + if(resolution_to_change_h != current_resolution_h) 23 | + { 24 | + GT_ChangeVideoResolution(); 25 | + printf("MAIN - Super resolution switched\n"); 26 | + } 27 | + else {printf("MAIN - Super resolution change bypassed\n");} 28 | + } 29 | + resolution_to_change = false; 30 | + } 31 | + // SLK - end 32 | + 33 | int16 *sound; 34 | int32 ssize; 35 | bool fskip; 36 | @@ -1463,6 +1488,22 @@ 37 | return(true); // FIXME! 38 | } 39 | 40 | +//SLK - called to change resolution 41 | +void GT_ChangeVideoResolution(void) 42 | +{ 43 | + // assert(MDFN_ThreadID() == GameThreadID); 44 | + MDFND_LockMutex(VTMutex); 45 | + NeedVideoSync++; 46 | + MDFND_UnlockMutex(VTMutex); 47 | + 48 | + MDFND_PostSem(VTWakeupSem); 49 | + while(NeedVideoSync && GameThreadRun) 50 | + { 51 | + Time::SleepMS(2); 52 | + } 53 | +} 54 | +//SLK - end 55 | + 56 | bool GT_ReinitSound(void) 57 | { 58 | bool ret = true; 59 | diff -Naur /mednafen/src/drivers/main.h /emu4crt/src/drivers/main.h 60 | --- /mednafen/src/drivers/main.h 2018-02-19 20:21:58.000000000 +0100 61 | +++ /emu4crt/src/drivers/main.h 2018-02-26 22:48:24.541435196 +0100 62 | @@ -68,7 +68,7 @@ 63 | void GT_ToggleFS(void); 64 | bool GT_ReinitVideo(void); 65 | bool GT_ReinitSound(void); 66 | - 67 | +void GT_ChangeVideoResolution(void); //SLK 68 | 69 | void BuildSystemSetting(MDFNSetting *setting, const char *system_name, const char *name, const char *description, const char *description_extra, MDFNSettingType type, 70 | const char *default_value, const char *minimum = NULL, const char *maximum = NULL, 71 | diff -Naur /mednafen/src/drivers/video.cpp /emu4crt/src/drivers/video.cpp 72 | --- /mednafen/src/drivers/video.cpp 2018-02-19 20:21:58.000000000 +0100 73 | +++ /emu4crt/src/drivers/video.cpp 2018-03-05 22:09:45.453863364 +0100 74 | @@ -105,6 +105,16 @@ 75 | VDRIVER__COUNT 76 | }; 77 | 78 | +// SLK 79 | +static int _resolution_switch; 80 | +enum 81 | +{ 82 | + RES_STATIC = 0, 83 | + RES_NATIVE = 1, 84 | + RES_SUPER = 2 85 | +}; 86 | +// SLK - end 87 | + 88 | enum 89 | { 90 | NTVB_NONE = 0, 91 | @@ -140,6 +150,17 @@ 92 | { NULL, 0 }, 93 | }; 94 | 95 | +// SLK - custom setting 96 | +static const MDFNSetting_EnumList Resolution_Switch[] = 97 | +{ 98 | + // Legacy: 99 | + { "0", RES_STATIC}, 100 | + { "native", RES_NATIVE, "Native resolution", gettext_noop("Use emulated system native resolution.") }, 101 | + { "super", RES_SUPER, "Super resolution", gettext_noop("Use super resolutions") }, 102 | + { NULL, 0 }, 103 | +}; 104 | +// SLK - end 105 | + 106 | static const MDFNSetting GlobalVideoSettings[] = 107 | { 108 | { "video.driver", MDFNSF_NOFLAGS, gettext_noop("Video output driver."), NULL, MDFNST_ENUM, "default", NULL, NULL, NULL, NULL, VDriver_List }, 109 | @@ -155,6 +176,11 @@ 110 | MDFNST_BOOL, "1" }, 111 | 112 | { "video.disable_composition", MDFNSF_NOFLAGS, gettext_noop("Attempt to disable desktop composition."), gettext_noop("Currently, this setting only has an effect on Windows Vista and Windows 7(and probably the equivalent server versions as well)."), MDFNST_BOOL, "1" }, 113 | + 114 | + // SLK - admit new parameter 115 | + { "video.resolution_switch", MDFNSF_NOFLAGS, gettext_noop("Video resolution switch (0, native or super)."), NULL, MDFNST_ENUM, "0", NULL, NULL, NULL, NULL, Resolution_Switch}, 116 | + // SLK - end 117 | + 118 | }; 119 | 120 | static const MDFNSetting_EnumList StretchMode_List[] = 121 | @@ -829,6 +855,41 @@ 122 | 123 | video_settings.shader = (ShaderType)MDFN_GetSettingI(snp + "shader"); 124 | video_settings.shader_str = MDFN_GetSettingS(snp + "shader"); 125 | + 126 | + // SLK - set video settings - disable some options in conflict with native resolution 127 | + _resolution_switch = MDFN_GetSettingI("video.resolution_switch"); 128 | + if(_resolution_switch) 129 | + { 130 | + if(_resolution_switch == RES_NATIVE) // Native Res 131 | + { 132 | + use_native_resolution = true; 133 | + printf("### VIDEO Native resolution init - set to %dx%d\n",resolution_to_change_w,resolution_to_change_h); 134 | + video_settings.xres = resolution_to_change_w; // for fullscreen mode 135 | + VideoGI->nominal_width = resolution_to_change_w; // for windowed mode 136 | + video_settings.xscale = 1; 137 | + video_settings.xscalefs = 1; 138 | + video_settings.yscalefs = 1; 139 | + video_settings.stretch = 0; 140 | + 141 | + } 142 | + if(_resolution_switch == RES_SUPER) 143 | + { 144 | + use_super_resolution = true; 145 | + printf("### VIDEO Super resolution init - set to 2560x%d\n",resolution_to_change_h); 146 | + video_settings.xres = current_resolution_w = 2560; // for fullscreen mode 147 | + VideoGI->nominal_width = 2560; // for windowed mode 148 | + video_settings.xscale = 1; 149 | + video_settings.xscalefs = 1; 150 | + video_settings.yscalefs = 1; 151 | + video_settings.stretch = 0; 152 | + } 153 | + video_settings.yres = current_resolution_h = resolution_to_change_h; // for fullscreen mode 154 | + VideoGI->nominal_height = resolution_to_change_h; // for windowed mode 155 | + video_settings.yscale = 1; 156 | + video_settings.videoip = 0; 157 | + video_settings.shader = SHADER_NONE; 158 | + } 159 | + 160 | // 161 | // 162 | if(0) 163 | @@ -1223,11 +1284,44 @@ 164 | SMRect.y = 0; 165 | SMRect.w = screen_w; 166 | 167 | - SMDRect.w = SMRect.w * xmu; 168 | + // SLK - Set OSD message rendering rect. 169 | + if(use_super_resolution) // enlarge OSD message in super resolution mode 170 | + { 171 | + SMDRect.w = SMRect.w * xmu; 172 | + printf("VIDEO - Init : SMRect.w: %d xmu: %d\n",SMRect.w,xmu); 173 | + } 174 | + else 175 | + { 176 | + SMDRect.w = SMRect.w * xmu; 177 | + } 178 | + // SLK - end 179 | + 180 | + //SMDRect.w = SMRect.w * xmu; 181 | SMDRect.h = SMRect.h * ymu; 182 | SMDRect.x = (screen_w - SMDRect.w) / 2; 183 | - SMDRect.y = screen_h - SMDRect.h; 184 | + // SMDRect.y = screen_h - SMDRect.h; 185 | 186 | + // SLK - Vertical offset for OSD messages 187 | + if(use_native_resolution || use_super_resolution) 188 | + { 189 | + switch(screen_h){ 190 | + case 240:SMDRect.y = screen_h - SMDRect.h - 18; 191 | + break; 192 | + case 288:SMDRect.y = screen_h - SMDRect.h - 32; 193 | + break; 194 | + case 480:SMDRect.y = screen_h - SMDRect.h - 32; 195 | + break; 196 | + case 576:SMDRect.y = screen_h - SMDRect.h - 64; 197 | + break; 198 | + default:SMDRect.y = screen_h - SMDRect.h * xmu; // TODO: ??? 199 | + } 200 | + } 201 | + else 202 | + { 203 | + SMDRect.y = screen_h - SMDRect.h; 204 | + } 205 | + // SLK - end 206 | + 207 | if(SMDRect.x < 0) 208 | { 209 | SMRect.w += SMDRect.x * 2 / xmu; 210 | @@ -1633,6 +1727,16 @@ 211 | 212 | if(LineWidths[0] == ~0) // Skip multi line widths code? 213 | { 214 | + // SLK - blit for: NES 215 | + //printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 216 | + //printf(" Dest: %dx%d - %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 217 | + // src_rect.y = (resolution_to_change_h - src_rect.h) / 2 ; //SLK 218 | + if(use_native_resolution || use_super_resolution) 219 | + { 220 | + screen_dest_rect.y = (resolution_to_change_h - src_rect.h) / 2; 221 | + screen_dest_rect.h = src_rect.h; 222 | + } 223 | + // SLK end 224 | SubBlit(msurface, src_rect, screen_dest_rect, InterlaceField); 225 | } 226 | else 227 | @@ -1672,28 +1776,60 @@ 228 | } 229 | else 230 | { 231 | - sub_dest_rect.x = screen_dest_rect.x; 232 | - sub_dest_rect.w = screen_dest_rect.w; 233 | - sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 234 | - sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 235 | - } 236 | - 237 | - if(!sub_dest_rect.h) // May occur with small yscale values in certain cases, so prevent triggering an assert() 238 | - sub_dest_rect.h = 1; 239 | - 240 | - // Blit here! 241 | - SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 242 | + if(use_native_resolution || use_super_resolution) 243 | + { 244 | + // SLK - (prevent) resizing and centering 245 | + //printf(" src_rect: %dx%d %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 246 | + sub_dest_rect.x = screen_dest_rect.x; 247 | + sub_dest_rect.w = screen_dest_rect.w; 248 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y); // * screen_dest_rect.h / src_rect.h; 249 | + //printf(" sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 250 | + //printf(" sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 251 | + //printf(" sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 252 | + 253 | + if(sub_src_rect.w >= resolution_to_change_w) // horizontal crop to fit screen 254 | + { 255 | + sub_src_rect.x = sub_src_rect.x + ((sub_src_rect.w - resolution_to_change_w) / 2); 256 | + sub_src_rect.w = resolution_to_change_w; 257 | + } 258 | + 259 | + if(native_resolution_vcenter == true) // default vertical centering 260 | + { 261 | + sub_dest_rect.y = sub_dest_rect.y + (resolution_to_change_h - sub_src_rect.h) / 2 ; 262 | + sub_dest_rect.h = sub_src_rect.h; 263 | + } 264 | + else // fill screen (psx - half black screen fix) 265 | + { 266 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 267 | + } 268 | + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 269 | + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 270 | + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 271 | + } 272 | + else 273 | + { 274 | + sub_dest_rect.x = screen_dest_rect.x; 275 | + sub_dest_rect.w = screen_dest_rect.w; 276 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 277 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 278 | + } 279 | + 280 | + if(!sub_dest_rect.h){sub_dest_rect.h = 1;} // May occur with small yscale values in certain cases, so prevent triggering an assert() 281 | + // SLK - end 282 | + 283 | + // Blit here! 284 | + SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 285 | 286 | - last_y = y; 287 | + last_y = y; 288 | 289 | - if(y != (src_rect.y + src_rect.h)) 290 | - { 291 | - last_width = LineWidths[y]; 292 | + if(y != (src_rect.y + src_rect.h)) 293 | + { 294 | + last_width = LineWidths[y]; 295 | + } 296 | } 297 | - 298 | - } 299 | } 300 | } 301 | + } 302 | 303 | if(take_ssnapshot) 304 | { 305 | diff -Naur /mednafen/src/drivers/video-state.cpp /emu4crt/src/drivers/video-state.cpp 306 | --- /mednafen/src/drivers/video-state.cpp 2018-02-19 20:21:58.000000000 +0100 307 | +++ /emu4crt/src/drivers/video-state.cpp 2018-03-05 20:28:36.493661111 +0100 308 | @@ -161,7 +161,7 @@ 309 | } // end if(StateStatus) 310 | 311 | if(PreviewSurface) 312 | - { 313 | +{ 314 | MDFN_Rect tdrect, drect; 315 | 316 | int meow = ((screen_w / CurGame->nominal_width) + 1) / 2; 317 | @@ -169,19 +169,51 @@ 318 | 319 | tdrect.w = TextRect.w * meow; 320 | tdrect.h = TextRect.h * meow; 321 | - tdrect.x = (screen_w - tdrect.w) / 2; 322 | - tdrect.y = screen_h - tdrect.h; 323 | - 324 | - BlitRaw(TextSurface, &TextRect, &tdrect); 325 | - 326 | - drect.w = PreviewRect.w * meow; 327 | - drect.h = PreviewRect.h * meow; 328 | - drect.x = (screen_w - drect.w) / 2; 329 | - drect.y = screen_h - drect.h - tdrect.h - 4; 330 | - 331 | - BlitRaw(PreviewSurface, &PreviewRect, &drect); 332 | - 333 | - } 334 | + tdrect.x = (screen_w - tdrect.w) / 2; 335 | + // SLK - Custom savestate selection OSD 336 | + if(use_native_resolution || use_super_resolution) 337 | + { 338 | + switch(screen_h){ 339 | + case 240:tdrect.y = screen_h - tdrect.h - 18; 340 | + break; 341 | + case 288:tdrect.y = screen_h - tdrect.h - 32; 342 | + break; 343 | + case 480:tdrect.y = screen_h - tdrect.h - 32; 344 | + break; 345 | + case 576:tdrect.y = screen_h - tdrect.h - 64; 346 | + break; 347 | + default:tdrect.y = screen_h - tdrect.h; 348 | + } 349 | + if(use_super_resolution) 350 | + { 351 | + tdrect.w = tdrect.w * 8; 352 | + tdrect.x = (screen_w - tdrect.w) / 2; 353 | + } 354 | + 355 | + BlitRaw(TextSurface, &TextRect, &tdrect); 356 | + 357 | + drect.w = screen_w * 0.5 + 3; // TODO: Why 3 ??? 358 | + drect.h = screen_h * 0.5 + 3; 359 | + drect.x = (screen_w - drect.w) / 2; 360 | + drect.y = tdrect.y - drect.h; // SLK 361 | + 362 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 363 | + } 364 | + else // native OSD display 365 | + { 366 | + tdrect.y = screen_h - tdrect.h; 367 | + 368 | + BlitRaw(TextSurface, &TextRect, &tdrect); 369 | + 370 | + drect.w = PreviewRect.w * meow; 371 | + drect.h = PreviewRect.h * meow; 372 | + drect.x = (screen_w - drect.w) / 2; 373 | + drect.y = screen_h - drect.h - tdrect.h - 4; 374 | + 375 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 376 | + } 377 | + // SLK - end 378 | + } 379 | 380 | } 381 | 382 | diff -Naur /mednafen/src/mednafen.cpp /emu4crt/src/mednafen.cpp 383 | --- /mednafen/src/mednafen.cpp 2018-02-19 20:21:58.000000000 +0100 384 | +++ /emu4crt/src/mednafen.cpp 2018-02-26 22:46:44.597119163 +0100 385 | @@ -57,6 +57,17 @@ 386 | static const char *CSD_tblur_accum = gettext_noop("Accumulate color data rather than discarding it."); 387 | static const char *CSD_tblur_accum_amount = gettext_noop("Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame."); 388 | 389 | +// SLK 390 | +bool use_native_resolution = false; 391 | +bool use_super_resolution = false; 392 | +bool resolution_to_change; 393 | +int resolution_to_change_w; 394 | +int resolution_to_change_h; 395 | +int current_resolution_w; 396 | +int current_resolution_h; 397 | +bool native_resolution_vcenter = true; 398 | +// SLK end 399 | + 400 | static const MDFNSetting_EnumList VCodec_List[] = 401 | { 402 | { "raw", (int)QTRecord::VCODEC_RAW, "Raw", 403 | @@ -850,10 +861,16 @@ 404 | { 405 | RMD_Drive dr; 406 | 407 | - dr.Name = std::string("Virtual CD Drive"); 408 | - dr.PossibleStates.push_back(RMD_State({"Tray Open", false, false, true})); 409 | - dr.PossibleStates.push_back(RMD_State({"Tray Closed (Empty)", false, false, false})); 410 | - dr.PossibleStates.push_back(RMD_State({"Tray Closed", true, true, false})); 411 | + // SLK - shorten messages to fit display in low-res modes 412 | + dr.Name = std::string("CD Drive"); 413 | + dr.PossibleStates.push_back(RMD_State({"Open", false, false, true})); 414 | + dr.PossibleStates.push_back(RMD_State({"Closed (Empty)", false, false, false})); 415 | + dr.PossibleStates.push_back(RMD_State({"Closed", true, true, false})); 416 | + //dr.Name = std::string("Virtual CD Drive"); 417 | + //dr.PossibleStates.push_back(RMD_State({"Tray Open", false, false, true})); 418 | + //dr.PossibleStates.push_back(RMD_State({"Tray Closed (Empty)", false, false, false})); 419 | + //dr.PossibleStates.push_back(RMD_State({"Tray Closed", true, true, false})); 420 | + // SLK end 421 | dr.CompatibleMedia.push_back(0); 422 | dr.MediaMtoPDelay = 2000; 423 | 424 | diff -Naur /mednafen/src/mednafen.h /emu4crt/src/mednafen.h 425 | --- /mednafen/src/mednafen.h 2018-02-19 20:21:58.000000000 +0100 426 | +++ /emu4crt/src/mednafen.h 2018-02-26 22:43:44.976637374 +0100 427 | @@ -24,6 +24,18 @@ 428 | 429 | extern MDFNGI *MDFNGameInfo; 430 | 431 | +// SLK 432 | +extern bool use_native_resolution; 433 | +extern bool use_super_resolution; 434 | +extern bool native_resolution_vcenter; 435 | +extern bool resolution_to_change; 436 | +extern int resolution_to_change_w; 437 | +extern int resolution_to_change_h; 438 | +extern int current_resolution_w; 439 | +extern int current_resolution_h; 440 | +// SLK end 441 | + 442 | + 443 | #include "settings.h" 444 | 445 | enum MDFN_NoticeType : uint8 446 | diff -Naur /mednafen/src/nes/nes.cpp /emu4crt/src/nes/nes.cpp 447 | --- /mednafen/src/nes/nes.cpp 2018-02-19 20:21:58.000000000 +0100 448 | +++ /emu4crt/src/nes/nes.cpp 2018-03-05 19:18:00.273009886 +0100 449 | @@ -289,7 +289,21 @@ 450 | MDFNGameInfo->fps = PAL? 838977920 : 1008307711; 451 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); 452 | } 453 | - 454 | + 455 | + //SLK 456 | + if(PAL) 457 | + { 458 | + resolution_to_change_h = 288; 459 | + } 460 | + else 461 | + { 462 | + resolution_to_change_h = 240; 463 | + } 464 | + resolution_to_change_w = 256; 465 | + resolution_to_change = true; 466 | + //SLK end 467 | + 468 | + 469 | X6502_Init(); 470 | MDFNPPU_Init(); 471 | MDFNSND_Init(PAL); 472 | diff -Naur /mednafen/src/pce/pce.cpp /emu4crt/src/pce/pce.cpp 473 | --- /mednafen/src/pce/pce.cpp 2018-02-19 20:21:58.000000000 +0100 474 | +++ /emu4crt/src/pce/pce.cpp 2018-03-05 19:21:32.921623951 +0100 475 | @@ -413,6 +413,16 @@ 476 | for(unsigned ch = 0; ch < 2; ch++) 477 | HRBufs[ch] = new OwlBuffer(); 478 | 479 | + // SLK 480 | + if(MDFN_GetSettingB("pce.arcadecard")) 481 | + { 482 | + resolution_to_change_w = 256; 483 | + resolution_to_change_h = 240; 484 | + resolution_to_change = true; 485 | + } 486 | + // SLK 487 | + 488 | + 489 | // FIXME: Make these globals less global! 490 | PCE_ACEnabled = MDFN_GetSettingB("pce.arcadecard"); 491 | 492 | diff -Naur /mednafen/src/pce/vce.cpp /emu4crt/src/pce/vce.cpp 493 | --- /mednafen/src/pce/vce.cpp 2018-02-19 20:21:58.000000000 +0100 494 | +++ /emu4crt/src/pce/vce.cpp 2018-03-05 19:22:54.645859294 +0100 495 | @@ -35,6 +35,11 @@ 496 | namespace MDFN_IEN_PCE 497 | { 498 | 499 | +// SLK 500 | +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start 501 | +static const int width_list[4] = {256, 320, 512, 512 }; // SLK 502 | +// SLK end 503 | + 504 | static const int vce_ratios[4] = { 4, 3, 2, 2 }; 505 | 506 | static MDFN_FASTCALL NO_INLINE int32 Sync(const int32 timestamp); 507 | @@ -628,6 +633,18 @@ 508 | dot_clock_ratio = vce_ratios[dot_clock]; 509 | 510 | CR = V; 511 | + 512 | + // SLK 513 | + if(dot_clock != prev_dot_clock) 514 | + { 515 | + printf("PCE - VCE - dot_clock change to: %d\n",dot_clock); 516 | + prev_dot_clock = dot_clock; 517 | + resolution_to_change_w = width_list[dot_clock]; 518 | + resolution_to_change_h = 240; 519 | + resolution_to_change = true; 520 | + } 521 | + // SLK end 522 | + 523 | } 524 | 525 | void VCE::SetPixelFormat(const MDFN_PixelFormat &format, const uint8* CustomColorMap, const uint32 CustomColorMapLen) 526 | diff -Naur /mednafen/src/psx/gpu.cpp /emu4crt/src/psx/gpu.cpp 527 | --- /mednafen/src/psx/gpu.cpp 2018-02-19 20:21:58.000000000 +0100 528 | +++ /emu4crt/src/psx/gpu.cpp 2018-03-05 22:45:50.460679333 +0100 529 | @@ -24,6 +24,7 @@ 530 | #include "psx.h" 531 | #include "timer.h" 532 | 533 | +#include // SLK 534 | /* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ 535 | 536 | /* 537 | @@ -74,6 +75,78 @@ 538 | } 539 | using namespace PS_GPU_INTERNAL; 540 | 541 | +// SLK 542 | +uint32 PreviousDisplayMode; 543 | +int prev_resolution_w; 544 | +int prev_resolution_h; 545 | +int res_change_count; 546 | + 547 | +void GPU_NewDisplayMode(int V) // SLK - identify GPU new resolution, set global variables used in MAIN & VIDEO 548 | +{ 549 | + // GP1(08h) - Display mode 550 | + // 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 551 | + // 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 552 | + // 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 553 | + // 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 554 | + // 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 555 | + // 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 556 | + // 7 "Reverseflag" (0=Normal, 1=Distorted) ;GPUSTAT.14 557 | + // source: http://problemkaputt.de/psx-spx.txt 558 | + 559 | + // Width 560 | + if((V & 0x40) == 0x40) 561 | + { 562 | + resolution_to_change_w = 368; 563 | + } 564 | + else 565 | + { 566 | + switch(V & 0x3) 567 | + { 568 | + case 0x00: 569 | + resolution_to_change_w = 256; 570 | + break; 571 | + case 0x01: 572 | + resolution_to_change_w = 320; 573 | + break; 574 | + case 0x02: 575 | + resolution_to_change_w = 512; 576 | + break; 577 | + case 0x03: 578 | + resolution_to_change_w = 640; 579 | + break; 580 | + } 581 | + } 582 | + // Height 583 | + if ((V & 8) == 8) 584 | + { //PAL 585 | + if ((V & 32) == 32) {resolution_to_change_h = 576;} //5 586 | + else {resolution_to_change_h = 288;} 587 | + } 588 | + else 589 | + { // NTSC 590 | + if ((V & 32) == 32){resolution_to_change_h = 480;} //5 591 | + else {resolution_to_change_h = 240;} 592 | + } 593 | + 594 | + if(prev_resolution_w != resolution_to_change_w || prev_resolution_h != resolution_to_change_h) 595 | + { 596 | + if(res_change_count < 2) 597 | + { 598 | + res_change_count += 1; 599 | + printf("PSX GPU - Startup resolution change bypass (%d).\n",res_change_count); 600 | + native_resolution_vcenter = false; // No need Vertical centering for PSX module. 601 | + } 602 | + else{ 603 | + prev_resolution_w = resolution_to_change_w; // will be used in VIDEO.cpp 604 | + prev_resolution_h = resolution_to_change_h; 605 | + printf("PSX - GPU register - resolution change to: %dx%d (V=%d)\n",resolution_to_change_w,resolution_to_change_h,V); 606 | + resolution_to_change = true; // will be reset in VIDEO.cpp 607 | + 608 | + } 609 | + } 610 | +} 611 | +// SLK end 612 | + 613 | void GPU_Init(bool pal_clock_and_tv) 614 | { 615 | static const int8 dither_table[4][4] = 616 | @@ -110,11 +183,25 @@ 617 | { 618 | GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) 619 | hmc_to_visible = 520; 620 | + 621 | + //SLK 622 | + resolution_to_change = true; 623 | + resolution_to_change_w = 640; 624 | + resolution_to_change_h = 480; 625 | + printf("PSX - GPU Init - NTSC mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 626 | + 627 | } 628 | else // PAL clock 629 | { 630 | GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) 631 | hmc_to_visible = 560; 632 | + 633 | + //SLK 634 | + resolution_to_change = true; 635 | + resolution_to_change_w = 640; 636 | + resolution_to_change_h = 576; 637 | + printf("PSX - GPU Init - PAL mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 638 | + 639 | } 640 | 641 | memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); 642 | @@ -879,6 +966,11 @@ 643 | case 0x08: 644 | //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); 645 | DisplayMode = V & 0xFF; 646 | + if(PreviousDisplayMode != DisplayMode) // SLK - Trap GPU resolution change 647 | + { 648 | + PreviousDisplayMode = DisplayMode; 649 | + GPU_NewDisplayMode(V); 650 | + } 651 | break; 652 | 653 | case 0x09: 654 | @@ -1093,8 +1185,13 @@ 655 | { 656 | static const uint32 DotClockRatios[5] = { 10, 8, 5, 4, 7 }; 657 | const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); 658 | - const uint32 dmw = 2800 / DotClockRatios[dmc]; // Must be <= (768 - 32) 659 | - const uint32 dmpa = (2800 - (hide_hoverscan ? 2640 : 2800)) / DotClockRatios[dmc] / 2; // Must be <= 32 660 | + 661 | + // Hotdog mod 662 | + // const uint32 dmw = 2800 / DotClockRatios[dmc]; // Must be <= (768 - 32) 663 | + // const uint32 dmpa = (2800 - (hide_hoverscan ? 2640 : 2800)) / DotClockRatios[dmc] / 2; // Must be <= 32 664 | + const uint32 dmw = 2560 / DotClockRatios[dmc]; // Must be <= (768 - 32) 665 | + const uint32 dmpa = 0; 666 | + // Hotdog mod - end 667 | const uint32 drxbo = 32; 668 | 669 | int32 sys_clocks = sys_timestamp - lastts; 670 | @@ -1342,6 +1439,16 @@ 671 | int32 fb_x = DisplayFB_XStart * 2; 672 | int32 dx_start = HorizStart, dx_end = HorizEnd; 673 | 674 | + // Hotdog mod - 384 675 | + int32 actualGameBufferWidth = (HorizEnd - HorizStart) / DotClockRatios[dmc]; 676 | + int32 ourBufferWidth = dmw; 677 | + 678 | + int32 leftOffset = (actualGameBufferWidth - ourBufferWidth) / 2; 679 | + //leftOffset *= DotClockRatios[dmc]; // Get back into PSX GPU co-ords. 680 | + leftOffset = std::max(leftOffset, 0); // Make sure not negative 681 | + dx_start += leftOffset; // Offset the PSX buffer to render relative to our frame. 682 | + // 683 | + 684 | dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 685 | dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 686 | 687 | @@ -1351,10 +1458,16 @@ 688 | dx_start = dx_start / DotClockRatios[dmc]; 689 | dx_end = dx_end / DotClockRatios[dmc]; 690 | 691 | - dx_start -= hmc_to_visible / DotClockRatios[dmc]; 692 | - dx_end -= hmc_to_visible / DotClockRatios[dmc]; 693 | - dx_start += 7; 694 | - dx_end += 7; 695 | + // Hotdogmod 696 | + dx_end -= dx_start; 697 | + dx_start = -leftOffset; 698 | + 699 | + // dx_start -= hmc_to_visible / DotClockRatios[dmc]; 700 | + // dx_end -= hmc_to_visible / DotClockRatios[dmc]; 701 | + // dx_start += 7; 702 | + // dx_end += 7; 703 | + // Hotdod mod - end 704 | + 705 | 706 | if(dx_start < 0) 707 | { 708 | diff -Naur /mednafen/src/snes/interface.cpp /emu4crt/src/snes/interface.cpp 709 | --- /mednafen/src/snes/interface.cpp 2018-02-19 20:21:58.000000000 +0100 710 | +++ /emu4crt/src/snes/interface.cpp 2018-03-05 19:25:48.498359054 +0100 711 | @@ -71,6 +71,11 @@ 712 | 713 | static std::vector ColorMap; // [32768] 714 | 715 | +// SLK 716 | +int prev_resolution_w; 717 | +int prev_resolution_h; 718 | +// SLK - end 719 | + 720 | static void BuildColorMap(MDFN_PixelFormat &format, uint8* CustomColorMap) 721 | { 722 | for(int x = 0; x < 32768; x++) 723 | @@ -546,6 +551,23 @@ 724 | MDFNGameInfo->fps = PAL ? 838977920 : 1008307711; 725 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(32040.5); 726 | 727 | + // SLK - init. dynamic display video resolution - progressive by default 728 | + printf("SNES Interface - Regional mode: %s \n",(PAL ? "PAL" : "NTSC")); 729 | + if(PAL) 730 | + { 731 | + resolution_to_change_h = 288; 732 | + } 733 | + else 734 | + { 735 | + printf(" Video mode set to 256 x 240\n"); 736 | + resolution_to_change_h = 240; 737 | + } 738 | + resolution_to_change_w = 256; 739 | + resolution_to_change = true; 740 | + prev_resolution_w = resolution_to_change_w; 741 | + prev_resolution_h = resolution_to_change_h; 742 | + // SLK - end 743 | + 744 | if(!snsf_loader) 745 | { 746 | EnableHBlend = MDFN_GetSettingB("snes.h_blend"); 747 | @@ -890,6 +912,32 @@ 748 | bSNES_v059::system.run_mednafen_custom(); 749 | bSNES_v059::ppu.enable_renderer(true); 750 | 751 | + // SLK - guess SNES active resolution 752 | + //printf("SNES Interface - Emulate - %dx%d - %d,%d\n",tdr->w,tdr->h,tdr->x,tdr->y); 753 | + if(tdr->h > 10 && tdr->w > 10 && tdr->w != prev_resolution_w) 754 | + { 755 | + resolution_to_change = true; 756 | + resolution_to_change_w = tdr->w; 757 | + } 758 | + if(tdr->h > 10 && tdr->w > 10 && tdr->h != prev_resolution_h) 759 | + { 760 | + resolution_to_change = true; 761 | + if(tdr->h <= 400) 762 | + { 763 | + resolution_to_change_h = bSNES_v059::system.region() ? 288 : 240; 764 | + } 765 | + else 766 | + { 767 | + resolution_to_change_h = bSNES_v059::system.region() ? 576 : 480; 768 | + } 769 | + } 770 | + if(resolution_to_change) 771 | + { 772 | + //printf("SNES - Interface - Resolution change detected: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 773 | + prev_resolution_w = resolution_to_change_w; 774 | + prev_resolution_h = tdr->h; 775 | + } 776 | + // SLK - end 777 | 778 | // 779 | // Blank out any missed lines(for e.g. display height change with PAL emulation) 780 | diff -Naur /mednafen/src/ss/vdp2_render.cpp /emu4crt/src/ss/vdp2_render.cpp 781 | --- /mednafen/src/ss/vdp2_render.cpp 2018-02-19 20:21:58.000000000 +0100 782 | +++ /emu4crt/src/ss/vdp2_render.cpp 2018-03-05 19:52:44.476427260 +0100 783 | @@ -144,6 +144,14 @@ 784 | static uint8 LineColorCCRatio; 785 | static uint8 BackCCRatio; 786 | 787 | +//SLK 788 | +static uint8 prev_InterlaceMode = 0; 789 | +static uint8 prev_HRes = 0; 790 | +static uint8 prev_VRes = 0; 791 | +static bool prev_BorderMode = 0; 792 | +// SLK end 793 | + 794 | + 795 | // 796 | static struct 797 | { 798 | @@ -549,6 +557,39 @@ 799 | InterlaceMode = (V >> 6) & 0x3; 800 | VRes = (V >> 4) & 0x3; 801 | HRes = (V >> 0) & 0x7; 802 | + // SLK 803 | + if(InterlaceMode != prev_InterlaceMode || HRes != prev_HRes) 804 | + { 805 | + printf("VDP2 Render - Television mode changed: %d\n",V); 806 | + printf(" BorderMode: %d\n",BorderMode); 807 | + printf(" PAL: %d\n",PAL); 808 | + printf(" InterlaceMode: %d\n",InterlaceMode); 809 | + printf(" VRes: %d\n",VRes); 810 | + printf(" HRes: %d\n",HRes); 811 | + prev_BorderMode = BorderMode; 812 | + prev_InterlaceMode = InterlaceMode; 813 | + prev_VRes = VRes; 814 | + prev_HRes = HRes; 815 | + // HRES 816 | + switch(HRes){ 817 | + case 0: 818 | + resolution_to_change_w = 320; 819 | + break; 820 | + case 1: 821 | + resolution_to_change_w = 352; 822 | + break; 823 | + case 2: 824 | + resolution_to_change_w = 640; 825 | + break; 826 | + case 3: 827 | + resolution_to_change_w = 704; 828 | + break; 829 | + } 830 | + if(InterlaceMode >= 2){resolution_to_change_h = PAL ? 576 : 480;} else {resolution_to_change_h = PAL ? 288 : 240;} 831 | + printf("SS - VDP2 Render - TV mode set to %dx%d",resolution_to_change_w,resolution_to_change_h); 832 | + resolution_to_change = true; // Flag for video resolution change by VIDEO.cpp/MAIN.cpp 833 | + } 834 | + // SLK - end 835 | break; 836 | 837 | case 0x02: 838 | @@ -3285,12 +3326,20 @@ 839 | { 840 | gi->nominal_width = (ShowHOverscan ? 365 : 354); 841 | gi->fb_height = 576; 842 | + resolution_to_change_h = 288; // SLK - init crt mode 843 | } 844 | else 845 | { 846 | gi->nominal_width = (ShowHOverscan ? 302 : 292); 847 | gi->fb_height = 480; 848 | + resolution_to_change_h = 240; // SLK - init crt mode 849 | } 850 | + // SLK 851 | + resolution_to_change_w = 320; 852 | + resolution_to_change = true; // SLK - init crt mode 853 | + // SLK - end 854 | + 855 | + 856 | gi->nominal_height = LineVisLast + 1 - LineVisFirst; 857 | 858 | gi->lcm_width = (ShowHOverscan? 10560 : 10240); 859 | diff -Naur /mednafen/src/state.cpp /emu4crt/src/state.cpp 860 | --- /mednafen/src/state.cpp 2018-02-19 20:21:58.000000000 +0100 861 | +++ /emu4crt/src/state.cpp 2018-03-05 20:34:59.867653268 +0100 862 | @@ -470,6 +470,14 @@ 863 | neowidth = MDFNGameInfo->nominal_width; 864 | neoheight = MDFNGameInfo->nominal_height; 865 | 866 | + // SLK - Approximation to prevent SaveState snapshot corruption 867 | + if(use_super_resolution) 868 | + { 869 | + neowidth = resolution_to_change_w; 870 | + neoheight = DisplayRect->h; 871 | + } 872 | + // SLK - end 873 | + 874 | if(LineWidths[0] != ~0) 875 | { 876 | int32 first_w = LineWidths[DisplayRect->y]; 877 | @@ -849,7 +857,9 @@ 878 | catch(std::exception &e) 879 | { 880 | if(!fname && !suffix) 881 | - MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 882 | + // SLK 883 | + // MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 884 | + MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d not found."), CurrentState); // SLK - shorten message to fit low-res rendering 885 | else 886 | MDFND_OutputNotice(MDFN_NOTICE_ERROR, e.what()); 887 | 888 | -------------------------------------------------------------------------------- /patches/mednafen-1.24.0-UNSTABLE-emu4crt-A09.patch: -------------------------------------------------------------------------------- 1 | diff -Naur -r --no-dereference ./mednafen/configure ./emu4crt/configure 2 | --- ./mednafen/configure 2019-12-24 04:24:48.000000000 -0800 3 | +++ ./emu4crt/configure 2019-12-26 07:29:42.895790000 -0800 4 | @@ -18085,7 +18085,8 @@ 5 | fi 6 | 7 | 8 | - LIBS="-mconsole -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 9 | +/* SLK - switch -mconsole */ 10 | + LIBS="-mwindows -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 11 | CPPFLAGS="-D_LFS64_LARGEFILE=1 $CPPFLAGS" 12 | elif expr x"$host" : 'x.*djgpp' > /dev/null; then 13 | 14 | diff -Naur -r --no-dereference ./mednafen/Documentation/modules.def ./emu4crt/Documentation/modules.def 15 | --- ./mednafen/Documentation/modules.def 2019-12-24 04:24:48.000000000 -0800 16 | +++ ./emu4crt/Documentation/modules.def 2019-12-26 14:09:26.590747231 -0800 17 | @@ -1,4 +1,4 @@ 18 | -1.24.0-UNSTABLE 19 | +1.24.0-UNSTABLE-emu4crt-A09 20 | apple2 21 | Apple II/II+ 22 | 250 23 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.cpp ./emu4crt/src/drivers/main.cpp 24 | --- ./mednafen/src/drivers/main.cpp 2019-12-24 04:24:48.000000000 -0800 25 | +++ ./emu4crt/src/drivers/main.cpp 2019-12-30 10:59:14.405782731 -0800 26 | @@ -273,6 +273,7 @@ 27 | MDFNGI *CurGame=NULL; 28 | 29 | 30 | + 31 | #ifdef WIN32 32 | static std::string GetModuleFileName_UTF8(HMODULE hModule) 33 | { 34 | @@ -287,6 +288,47 @@ 35 | return UTF16_to_UTF8(&path[0], nullptr, true); 36 | } 37 | 38 | + 39 | +static bool HandleConsoleMadness(void) // SLK - enforce stdout.txt & stderr.txt out to files 40 | +{ 41 | + bool ret; 42 | + if(AllocConsole()) 43 | + { 44 | + HWND cwin = GetConsoleWindow(); 45 | + ShowWindow(cwin, SW_HIDE); 46 | + 47 | + freopen("CONOUT$", "w", stdout); 48 | + freopen("CONOUT$", "w", stderr); 49 | + 50 | + SetConsoleOutputCP(65001); // UTF-8 51 | + 52 | + std::string path; 53 | + size_t catpos; // Meow meow. 54 | + path = GetModuleFileName_UTF8(NULL); 55 | + if((catpos = path.find_last_of('\\')) != std::string::npos) path.resize(catpos + 1); 56 | + const std::u16string stdout_path = UTF8_to_UTF16(path + "stdout.txt", nullptr, true); 57 | + const std::u16string stderr_path = UTF8_to_UTF16(path + "stderr.txt", nullptr, true); 58 | + int new_stdout = -1; 59 | + int new_stderr = -1; 60 | + new_stdout = _wopen((const wchar_t*)stdout_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 61 | + new_stderr = _wopen((const wchar_t*)stderr_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 62 | + 63 | + fflush(stdout); 64 | + fflush(stderr); 65 | + 66 | + dup2(new_stdout, fileno(stdout)); 67 | + dup2(new_stderr, fileno(stderr)); 68 | + 69 | + close(new_stdout); 70 | + close(new_stderr); 71 | + 72 | + } 73 | + ret = false; 74 | + return ret; 75 | +} 76 | + 77 | +/* // SLK - Disable native redirection functions due to switch back to windows application 78 | + 79 | // returns 1 if redirected, 0 if not redirected due to error, -1 if not redirected due to env variable 80 | static int RedirectSTDxxx(void) 81 | { 82 | @@ -398,6 +440,8 @@ 83 | 84 | return ret; 85 | } 86 | +*/ 87 | + 88 | #endif 89 | 90 | void Mednafen::MDFND_OutputNotice(MDFN_NoticeType t, const char* s) noexcept 91 | @@ -1267,56 +1311,79 @@ 92 | { 93 | while(GameThreadRun) 94 | { 95 | - int16 *sound; 96 | - int32 ssize; 97 | - bool fskip; 98 | - 99 | + //SLK trap change resolution request 100 | + if(resolution_to_change) 101 | + { 102 | + if(use_native_resolution) 103 | + { 104 | + if((current_resolution_w != resolution_to_change_w) || (current_resolution_h != resolution_to_change_h)) 105 | + { 106 | + GT_ChangeVideoResolution(); 107 | + printf("MAIN - native resolution switched\n"); 108 | + } 109 | + else {printf("MAIN - resolution change bypassed\n");} 110 | + } 111 | + if(use_super_resolution) 112 | + { 113 | + if(resolution_to_change_h != current_resolution_h) 114 | + { 115 | + GT_ChangeVideoResolution(); 116 | + printf("MAIN - Super resolution switched\n"); 117 | + } 118 | + else {printf("MAIN - Super resolution change bypassed\n");} 119 | + } 120 | + resolution_to_change = false; 121 | + } 122 | + // SLK - end 123 | + int16 *sound; 124 | + int32 ssize; 125 | + bool fskip; 126 | + 127 | /* If we requested a new video mode, wait until it's set before calling the emulation code again. 128 | */ 129 | - while(NeedVideoSync) 130 | - { 131 | - if(!GameThreadRun) return(1); // Might happen if video initialization failed 132 | + while(NeedVideoSync) 133 | + { 134 | + if(!GameThreadRun) return(1); // Might happen if video initialization failed 135 | Time::SleepMS(2); 136 | - } 137 | - 138 | - if(Sound_NeedReInit()) 139 | - GT_ReinitSound(); 140 | + } 141 | + if(Sound_NeedReInit()) 142 | + GT_ReinitSound(); 143 | 144 | - if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 145 | - ers.SetETtoRT(); 146 | - // 147 | - // 148 | - fskip = ers.NeedFrameSkip(); 149 | - fskip &= MDFN_GetSettingB("video.frameskip"); 150 | - fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 151 | - fskip |= (bool)NoWaiting; 152 | + if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 153 | + ers.SetETtoRT(); 154 | + // 155 | + // 156 | + fskip = ers.NeedFrameSkip(); 157 | + fskip &= MDFN_GetSettingB("video.frameskip"); 158 | + fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 159 | + fskip |= (bool)NoWaiting; 160 | 161 | - //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 162 | + //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 163 | 164 | - NeedFrameAdvance = false; 165 | - // 166 | - // 167 | - SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 168 | + NeedFrameAdvance = false; 169 | + // 170 | + // 171 | + SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 172 | 173 | - // 174 | - // 175 | - // 176 | - EmulateSpecStruct espec; 177 | + // 178 | + // 179 | + // 180 | + EmulateSpecStruct espec; 181 | 182 | - espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 183 | - espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 184 | - espec.skip = fskip; 185 | - espec.soundmultiplier = CurGameSpeed; 186 | - espec.NeedRewind = DNeedRewind; 187 | - 188 | - espec.SoundRate = Sound_GetRate(); 189 | - espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 190 | - espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 191 | + espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 192 | + espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 193 | + espec.skip = fskip; 194 | + espec.soundmultiplier = CurGameSpeed; 195 | + espec.NeedRewind = DNeedRewind; 196 | + 197 | + espec.SoundRate = Sound_GetRate(); 198 | + espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 199 | + espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 200 | 201 | - if(MDFN_UNLIKELY(StateRCTest)) 202 | - { 203 | - // Note: Won't work correctly with modules that do mid-sync. 204 | - EmulateSpecStruct estmp = espec; 205 | + if(MDFN_UNLIKELY(StateRCTest)) 206 | + { 207 | + // Note: Won't work correctly with modules that do mid-sync. 208 | + EmulateSpecStruct estmp = espec; 209 | 210 | MemoryStream state0(524288); 211 | MemoryStream state1(524288); 212 | @@ -1334,19 +1401,19 @@ 213 | 214 | if(!(state1.map_size() == state2.map_size() && !memcmp(state1.map() + 32, state2.map() + 32, state1.map_size() - 32))) 215 | { 216 | - FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 217 | - FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 218 | + FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 219 | + FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 220 | 221 | - sd0.write(state1.map(), state1.map_size()); 222 | - sd1.write(state2.map(), state2.map_size()); 223 | - sd0.close(); 224 | - sd1.close(); 225 | - //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 226 | - abort(); 227 | + sd0.write(state1.map(), state1.map_size()); 228 | + sd1.write(state2.map(), state2.map_size()); 229 | + sd0.close(); 230 | + sd1.close(); 231 | + //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 232 | + abort(); 233 | } 234 | - } 235 | - else 236 | - MDFNI_Emulate(&espec); 237 | + } 238 | + else 239 | + MDFNI_Emulate(&espec); 240 | 241 | if(MDFN_UNLIKELY(StateSLSTest)) 242 | { 243 | @@ -1591,6 +1658,22 @@ 244 | return(true); // FIXME! 245 | } 246 | 247 | +//SLK - called to change resolution 248 | +void GT_ChangeVideoResolution(void) 249 | +{ 250 | + // assert(MDFN_ThreadID() == GameThreadID); 251 | + MThreading::Mutex_Lock(VTMutex); 252 | + NeedVideoSync++; 253 | + MThreading::Mutex_Unlock(VTMutex); 254 | + 255 | + MThreading::Sem_Post(VTWakeupSem); 256 | + while(NeedVideoSync && GameThreadRun) 257 | + { 258 | + Time::SleepMS(2); 259 | + } 260 | +} 261 | +//SLK - end 262 | + 263 | bool GT_ReinitSound(void) 264 | { 265 | bool ret = true; 266 | @@ -2149,7 +2232,7 @@ 267 | } 268 | 269 | #ifdef WIN32 270 | - HandleConsoleMadness(); 271 | + HandleConsoleMadness(); // SLK 272 | #endif 273 | 274 | //ThreadTest(); 275 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.h ./emu4crt/src/drivers/main.h 276 | --- ./mednafen/src/drivers/main.h 2019-12-24 04:24:48.000000000 -0800 277 | +++ ./emu4crt/src/drivers/main.h 2019-12-26 07:31:19.371343000 -0800 278 | @@ -69,7 +69,7 @@ 279 | void GT_ToggleFS(void); 280 | bool GT_ReinitVideo(void); 281 | bool GT_ReinitSound(void); 282 | - 283 | +void GT_ChangeVideoResolution(void); //SLK 284 | 285 | void BuildSystemSetting(MDFNSetting *setting, const char *system_name, const char *name, const char *description, const char *description_extra, MDFNSettingType type, 286 | const char *default_value, const char *minimum = NULL, const char *maximum = NULL, 287 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video.cpp ./emu4crt/src/drivers/video.cpp 288 | --- ./mednafen/src/drivers/video.cpp 2019-12-24 04:24:48.000000000 -0800 289 | +++ ./emu4crt/src/drivers/video.cpp 2019-12-26 07:31:19.371343000 -0800 290 | @@ -105,6 +105,16 @@ 291 | VDRIVER__COUNT 292 | }; 293 | 294 | +// SLK 295 | +static int _resolution_switch; 296 | +enum 297 | +{ 298 | + RES_STATIC = 0, 299 | + RES_NATIVE = 1, 300 | + RES_SUPER = 2 301 | +}; 302 | +// SLK - end 303 | + 304 | enum 305 | { 306 | NTVB_NONE = 0, 307 | @@ -146,6 +156,17 @@ 308 | { NULL, 0 }, 309 | }; 310 | 311 | +// SLK - custom setting 312 | +static const MDFNSetting_EnumList Resolution_Switch[] = 313 | +{ 314 | + // Legacy: 315 | + { "0", RES_STATIC}, 316 | + { "native", RES_NATIVE, "Native resolution", gettext_noop("Use emulated system native resolution.") }, 317 | + { "super", RES_SUPER, "Super resolution", gettext_noop("Use super resolutions") }, 318 | + { NULL, 0 }, 319 | +}; 320 | +// SLK - end 321 | + 322 | static const MDFNSetting GlobalVideoSettings[] = 323 | { 324 | { "video.driver", MDFNSF_NOFLAGS, gettext_noop("Video output driver."), NULL, MDFNST_ENUM, "default", NULL, NULL, NULL, NULL, VDriver_List }, 325 | @@ -161,6 +182,11 @@ 326 | MDFNST_BOOL, "1" }, 327 | 328 | { "video.disable_composition", MDFNSF_NOFLAGS, gettext_noop("Attempt to disable desktop composition."), gettext_noop("Currently, this setting only has an effect on Windows Vista and Windows 7(and probably the equivalent server versions as well)."), MDFNST_BOOL, "1" }, 329 | + 330 | + // SLK - admit new parameter 331 | + { "video.resolution_switch", MDFNSF_NOFLAGS, gettext_noop("Video resolution switch (0, native or super)."), NULL, MDFNST_ENUM, "0", NULL, NULL, NULL, NULL, Resolution_Switch}, 332 | + // SLK - end 333 | + 334 | }; 335 | 336 | static const MDFNSetting_EnumList StretchMode_List[] = 337 | @@ -844,6 +870,41 @@ 338 | 339 | video_settings.shader = (ShaderType)MDFN_GetSettingI(snp + "shader"); 340 | video_settings.shader_str = MDFN_GetSettingS(snp + "shader"); 341 | + 342 | + // SLK - set video settings - disable some options in conflict with native resolution 343 | + _resolution_switch = MDFN_GetSettingI("video.resolution_switch"); 344 | + if(_resolution_switch) 345 | + { 346 | + if(_resolution_switch == RES_NATIVE) // Native Res 347 | + { 348 | + use_native_resolution = true; 349 | + printf("### VIDEO Native resolution init - set to %dx%d\n",resolution_to_change_w,resolution_to_change_h); 350 | + video_settings.xres = resolution_to_change_w; // for fullscreen mode 351 | + VideoGI->nominal_width = resolution_to_change_w; // for windowed mode 352 | + video_settings.xscale = 1; 353 | + video_settings.xscalefs = 1; 354 | + video_settings.yscalefs = 1; 355 | + video_settings.stretch = 0; 356 | + 357 | + } 358 | + if(_resolution_switch == RES_SUPER) 359 | + { 360 | + use_super_resolution = true; 361 | + printf("### VIDEO Super resolution init - set to 2560x%d\n",resolution_to_change_h); 362 | + video_settings.xres = current_resolution_w = 2560; // for fullscreen mode 363 | + VideoGI->nominal_width = 2560; // for windowed mode 364 | + video_settings.xscale = 1; 365 | + video_settings.xscalefs = 1; 366 | + video_settings.yscalefs = 1; 367 | + video_settings.stretch = 0; 368 | + } 369 | + video_settings.yres = current_resolution_h = resolution_to_change_h; // for fullscreen mode 370 | + VideoGI->nominal_height = resolution_to_change_h; // for windowed mode 371 | + video_settings.yscale = 1; 372 | + video_settings.videoip = 0; 373 | + video_settings.shader = SHADER_NONE; 374 | + } 375 | + 376 | // 377 | // 378 | if(0) 379 | @@ -1238,11 +1299,44 @@ 380 | SMRect.y = 0; 381 | SMRect.w = screen_w; 382 | 383 | - SMDRect.w = SMRect.w * xmu; 384 | + // SLK - Set OSD message rendering rect. 385 | + if(use_super_resolution) // enlarge OSD message in super resolution mode 386 | + { 387 | + SMDRect.w = SMRect.w * xmu; 388 | + printf("VIDEO - Init : SMRect.w: %d xmu: %d\n",SMRect.w,xmu); 389 | + } 390 | + else 391 | + { 392 | + SMDRect.w = SMRect.w * xmu; 393 | + } 394 | + // SLK - end 395 | + 396 | + //SMDRect.w = SMRect.w * xmu; 397 | SMDRect.h = SMRect.h * ymu; 398 | SMDRect.x = (screen_w - SMDRect.w) / 2; 399 | - SMDRect.y = screen_h - SMDRect.h; 400 | + // SMDRect.y = screen_h - SMDRect.h; 401 | 402 | + // SLK - Vertical offset for OSD messages 403 | + if(use_native_resolution || use_super_resolution) 404 | + { 405 | + switch(screen_h){ 406 | + case 240:SMDRect.y = screen_h - SMDRect.h - 18; 407 | + break; 408 | + case 288:SMDRect.y = screen_h - SMDRect.h - 32; 409 | + break; 410 | + case 480:SMDRect.y = screen_h - SMDRect.h - 32; 411 | + break; 412 | + case 576:SMDRect.y = screen_h - SMDRect.h - 64; 413 | + break; 414 | + default:SMDRect.y = screen_h - SMDRect.h * xmu; // TODO: ??? 415 | + } 416 | + } 417 | + else 418 | + { 419 | + SMDRect.y = screen_h - SMDRect.h; 420 | + } 421 | + // SLK - end 422 | + 423 | if(SMDRect.x < 0) 424 | { 425 | SMRect.w += SMDRect.x * 2 / xmu; 426 | @@ -1648,6 +1742,16 @@ 427 | 428 | if(LineWidths[0] == ~0) // Skip multi line widths code? 429 | { 430 | + // SLK - blit for: NES 431 | + //printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 432 | + //printf(" Dest: %dx%d - %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 433 | + // src_rect.y = (resolution_to_change_h - src_rect.h) / 2 ; //SLK 434 | + if(use_native_resolution || use_super_resolution) 435 | + { 436 | + screen_dest_rect.y = (resolution_to_change_h - src_rect.h) / 2; 437 | + screen_dest_rect.h = src_rect.h; 438 | + } 439 | + // SLK end 440 | SubBlit(msurface, src_rect, screen_dest_rect, InterlaceField); 441 | } 442 | else 443 | @@ -1687,28 +1791,60 @@ 444 | } 445 | else 446 | { 447 | - sub_dest_rect.x = screen_dest_rect.x; 448 | - sub_dest_rect.w = screen_dest_rect.w; 449 | - sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 450 | - sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 451 | - } 452 | - 453 | - if(!sub_dest_rect.h) // May occur with small yscale values in certain cases, so prevent triggering an assert() 454 | - sub_dest_rect.h = 1; 455 | - 456 | - // Blit here! 457 | - SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 458 | + if(use_native_resolution || use_super_resolution) 459 | + { 460 | + // SLK - (prevent) resizing and centering 461 | + //printf(" src_rect: %dx%d %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 462 | + sub_dest_rect.x = screen_dest_rect.x; 463 | + sub_dest_rect.w = screen_dest_rect.w; 464 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y); // * screen_dest_rect.h / src_rect.h; 465 | + //printf(" sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 466 | + //printf(" sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 467 | + //printf(" sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 468 | + 469 | + if(sub_src_rect.w >= resolution_to_change_w) // horizontal crop to fit screen 470 | + { 471 | + sub_src_rect.x = sub_src_rect.x + ((sub_src_rect.w - resolution_to_change_w) / 2); 472 | + sub_src_rect.w = resolution_to_change_w; 473 | + } 474 | + 475 | + if(native_resolution_vcenter == true) // default vertical centering 476 | + { 477 | + sub_dest_rect.y = sub_dest_rect.y + (resolution_to_change_h - sub_src_rect.h) / 2 ; 478 | + sub_dest_rect.h = sub_src_rect.h; 479 | + } 480 | + else // fill screen (psx - half black screen fix) 481 | + { 482 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 483 | + } 484 | + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 485 | + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 486 | + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 487 | + } 488 | + else 489 | + { 490 | + sub_dest_rect.x = screen_dest_rect.x; 491 | + sub_dest_rect.w = screen_dest_rect.w; 492 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 493 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 494 | + } 495 | + 496 | + if(!sub_dest_rect.h){sub_dest_rect.h = 1;} // May occur with small yscale values in certain cases, so prevent triggering an assert() 497 | + // SLK - end 498 | + 499 | + // Blit here! 500 | + SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 501 | 502 | - last_y = y; 503 | + last_y = y; 504 | 505 | - if(y != (src_rect.y + src_rect.h)) 506 | - { 507 | - last_width = LineWidths[y]; 508 | + if(y != (src_rect.y + src_rect.h)) 509 | + { 510 | + last_width = LineWidths[y]; 511 | + } 512 | } 513 | - 514 | - } 515 | } 516 | } 517 | + } 518 | 519 | if(take_ssnapshot) 520 | { 521 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video-state.cpp ./emu4crt/src/drivers/video-state.cpp 522 | --- ./mednafen/src/drivers/video-state.cpp 2019-12-24 04:24:48.000000000 -0800 523 | +++ ./emu4crt/src/drivers/video-state.cpp 2019-12-26 07:31:19.375343000 -0800 524 | @@ -161,7 +161,7 @@ 525 | } // end if(StateStatus) 526 | 527 | if(PreviewSurface) 528 | - { 529 | +{ 530 | MDFN_Rect tdrect, drect; 531 | 532 | int meow = ((screen_w / CurGame->nominal_width) + 1) / 2; 533 | @@ -169,19 +169,51 @@ 534 | 535 | tdrect.w = TextRect.w * meow; 536 | tdrect.h = TextRect.h * meow; 537 | - tdrect.x = (screen_w - tdrect.w) / 2; 538 | - tdrect.y = screen_h - tdrect.h; 539 | - 540 | - BlitRaw(TextSurface, &TextRect, &tdrect); 541 | - 542 | - drect.w = PreviewRect.w * meow; 543 | - drect.h = PreviewRect.h * meow; 544 | - drect.x = (screen_w - drect.w) / 2; 545 | - drect.y = screen_h - drect.h - tdrect.h - 4; 546 | - 547 | - BlitRaw(PreviewSurface, &PreviewRect, &drect); 548 | - 549 | - } 550 | + tdrect.x = (screen_w - tdrect.w) / 2; 551 | + // SLK - Custom savestate selection OSD 552 | + if(use_native_resolution || use_super_resolution) 553 | + { 554 | + switch(screen_h){ 555 | + case 240:tdrect.y = screen_h - tdrect.h - 18; 556 | + break; 557 | + case 288:tdrect.y = screen_h - tdrect.h - 32; 558 | + break; 559 | + case 480:tdrect.y = screen_h - tdrect.h - 32; 560 | + break; 561 | + case 576:tdrect.y = screen_h - tdrect.h - 64; 562 | + break; 563 | + default:tdrect.y = screen_h - tdrect.h; 564 | + } 565 | + if(use_super_resolution) 566 | + { 567 | + tdrect.w = tdrect.w * 8; 568 | + tdrect.x = (screen_w - tdrect.w) / 2; 569 | + } 570 | + 571 | + BlitRaw(TextSurface, &TextRect, &tdrect); 572 | + 573 | + drect.w = screen_w * 0.5 + 3; // TODO: Why 3 ??? 574 | + drect.h = screen_h * 0.5 + 3; 575 | + drect.x = (screen_w - drect.w) / 2; 576 | + drect.y = tdrect.y - drect.h; // SLK 577 | + 578 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 579 | + } 580 | + else // native OSD display 581 | + { 582 | + tdrect.y = screen_h - tdrect.h; 583 | + 584 | + BlitRaw(TextSurface, &TextRect, &tdrect); 585 | + 586 | + drect.w = PreviewRect.w * meow; 587 | + drect.h = PreviewRect.h * meow; 588 | + drect.x = (screen_w - drect.w) / 2; 589 | + drect.y = screen_h - drect.h - tdrect.h - 4; 590 | + 591 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 592 | + } 593 | + // SLK - end 594 | + } 595 | 596 | } 597 | 598 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.cpp ./emu4crt/src/mednafen.cpp 599 | --- ./mednafen/src/mednafen.cpp 2019-12-24 04:24:48.000000000 -0800 600 | +++ ./emu4crt/src/mednafen.cpp 2019-12-26 07:31:19.375343000 -0800 601 | @@ -51,6 +51,18 @@ 602 | #include "video/tblur.h" 603 | #include "qtrecord.h" 604 | 605 | +// SLK 606 | +bool use_native_resolution = false; 607 | +bool use_super_resolution = false; 608 | +bool resolution_to_change; 609 | +int resolution_to_change_w; 610 | +int resolution_to_change_h; 611 | +int current_resolution_w; 612 | +int current_resolution_h; 613 | +bool native_resolution_vcenter = true; 614 | +// SLK end 615 | + 616 | + 617 | namespace Mednafen 618 | { 619 | 620 | @@ -64,6 +76,17 @@ 621 | static const char *CSD_tblur_accum = gettext_noop("Accumulate color data rather than discarding it."); 622 | static const char *CSD_tblur_accum_amount = gettext_noop("Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame."); 623 | 624 | +// SLK 625 | +bool use_native_resolution = false; 626 | +bool use_super_resolution = false; 627 | +bool resolution_to_change; 628 | +int resolution_to_change_w; 629 | +int resolution_to_change_h; 630 | +int current_resolution_w; 631 | +int current_resolution_h; 632 | +bool native_resolution_vcenter = true; 633 | +// SLK end 634 | + 635 | static const MDFNSetting_EnumList VCodec_List[] = 636 | { 637 | { "raw", (int)QTRecord::VCODEC_RAW, "Raw", 638 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.h ./emu4crt/src/mednafen.h 639 | --- ./mednafen/src/mednafen.h 2019-12-24 04:24:48.000000000 -0800 640 | +++ ./emu4crt/src/mednafen.h 2019-12-26 07:31:19.375343000 -0800 641 | @@ -21,6 +21,18 @@ 642 | #include "settings.h" 643 | #include "NativeVFS.h" 644 | 645 | +// SLK 646 | +extern bool use_native_resolution; 647 | +extern bool use_super_resolution; 648 | +extern bool native_resolution_vcenter; 649 | +extern bool resolution_to_change; 650 | +extern int resolution_to_change_w; 651 | +extern int resolution_to_change_h; 652 | +extern int current_resolution_w; 653 | +extern int current_resolution_h; 654 | +// SLK end 655 | + 656 | + 657 | namespace Mednafen 658 | { 659 | MDFN_HIDE extern NativeVFS NVFS; 660 | diff -Naur -r --no-dereference ./mednafen/src/nes/nes.cpp ./emu4crt/src/nes/nes.cpp 661 | --- ./mednafen/src/nes/nes.cpp 2019-12-24 04:24:48.000000000 -0800 662 | +++ ./emu4crt/src/nes/nes.cpp 2019-12-26 07:31:19.375343000 -0800 663 | @@ -287,7 +287,21 @@ 664 | MDFNGameInfo->fps = PAL? 838977920 : 1008307711; 665 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); 666 | } 667 | - 668 | + 669 | + //SLK 670 | + if(PAL) 671 | + { 672 | + resolution_to_change_h = 288; 673 | + } 674 | + else 675 | + { 676 | + resolution_to_change_h = 240; 677 | + } 678 | + resolution_to_change_w = 256; 679 | + resolution_to_change = true; 680 | + //SLK end 681 | + 682 | + 683 | X6502_Init(); 684 | MDFNPPU_Init(); 685 | MDFNSND_Init(PAL); 686 | diff -Naur -r --no-dereference ./mednafen/src/pce/pce.cpp ./emu4crt/src/pce/pce.cpp 687 | --- ./mednafen/src/pce/pce.cpp 2019-12-24 04:24:48.000000000 -0800 688 | +++ ./emu4crt/src/pce/pce.cpp 2019-12-26 07:31:19.379343000 -0800 689 | @@ -414,6 +414,16 @@ 690 | for(unsigned ch = 0; ch < 2; ch++) 691 | HRBufs[ch] = new OwlBuffer(); 692 | 693 | + // SLK 694 | + if(MDFN_GetSettingB("pce.arcadecard")) 695 | + { 696 | + resolution_to_change_w = 256; 697 | + resolution_to_change_h = 240; 698 | + resolution_to_change = true; 699 | + } 700 | + // SLK 701 | + 702 | + 703 | // FIXME: Make these globals less global! 704 | PCE_ACEnabled = MDFN_GetSettingB("pce.arcadecard"); 705 | 706 | diff -Naur -r --no-dereference ./mednafen/src/pce/vce.cpp ./emu4crt/src/pce/vce.cpp 707 | --- ./mednafen/src/pce/vce.cpp 2019-12-24 04:24:48.000000000 -0800 708 | +++ ./emu4crt/src/pce/vce.cpp 2019-12-26 07:31:19.379343000 -0800 709 | @@ -35,6 +35,11 @@ 710 | namespace MDFN_IEN_PCE 711 | { 712 | 713 | +// SLK 714 | +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start 715 | +static const int width_list[4] = {256, 320, 512, 512 }; // SLK 716 | +// SLK end 717 | + 718 | static const int vce_ratios[4] = { 4, 3, 2, 2 }; 719 | 720 | static MDFN_FASTCALL NO_INLINE int32 Sync(const int32 timestamp); 721 | @@ -634,6 +639,18 @@ 722 | dot_clock_ratio = vce_ratios[dot_clock]; 723 | 724 | CR = V; 725 | + 726 | + // SLK 727 | + if(dot_clock != prev_dot_clock) 728 | + { 729 | + printf("PCE - VCE - dot_clock change to: %d\n",dot_clock); 730 | + prev_dot_clock = dot_clock; 731 | + resolution_to_change_w = width_list[dot_clock]; 732 | + resolution_to_change_h = 240; 733 | + resolution_to_change = true; 734 | + } 735 | + // SLK end 736 | + 737 | } 738 | 739 | void VCE::SetPixelFormat(const MDFN_PixelFormat &format, const uint8* CustomColorMap, const uint32 CustomColorMapLen) 740 | diff -Naur -r --no-dereference ./mednafen/src/psx/gpu.cpp ./emu4crt/src/psx/gpu.cpp 741 | --- ./mednafen/src/psx/gpu.cpp 2019-12-24 04:24:48.000000000 -0800 742 | +++ ./emu4crt/src/psx/gpu.cpp 2019-12-26 07:31:19.379343000 -0800 743 | @@ -24,6 +24,7 @@ 744 | #include "psx.h" 745 | #include "timer.h" 746 | 747 | +#include // SLK 748 | /* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ 749 | 750 | /* 751 | @@ -74,6 +75,78 @@ 752 | } 753 | using namespace PS_GPU_INTERNAL; 754 | 755 | +// SLK 756 | +uint32 PreviousDisplayMode; 757 | +int prev_resolution_w; 758 | +int prev_resolution_h; 759 | +int res_change_count; 760 | + 761 | +void GPU_NewDisplayMode(int V) // SLK - identify GPU new resolution, set global variables used in MAIN & VIDEO 762 | +{ 763 | + // GP1(08h) - Display mode 764 | + // 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 765 | + // 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 766 | + // 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 767 | + // 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 768 | + // 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 769 | + // 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 770 | + // 7 "Reverseflag" (0=Normal, 1=Distorted) ;GPUSTAT.14 771 | + // source: http://problemkaputt.de/psx-spx.txt 772 | + 773 | + // Width 774 | + if((V & 0x40) == 0x40) 775 | + { 776 | + resolution_to_change_w = 368; 777 | + } 778 | + else 779 | + { 780 | + switch(V & 0x3) 781 | + { 782 | + case 0x00: 783 | + resolution_to_change_w = 256; 784 | + break; 785 | + case 0x01: 786 | + resolution_to_change_w = 320; 787 | + break; 788 | + case 0x02: 789 | + resolution_to_change_w = 512; 790 | + break; 791 | + case 0x03: 792 | + resolution_to_change_w = 640; 793 | + break; 794 | + } 795 | + } 796 | + // Height 797 | + if ((V & 8) == 8) 798 | + { //PAL 799 | + if ((V & 32) == 32) {resolution_to_change_h = 576;} //5 800 | + else {resolution_to_change_h = 288;} 801 | + } 802 | + else 803 | + { // NTSC 804 | + if ((V & 32) == 32){resolution_to_change_h = 480;} //5 805 | + else {resolution_to_change_h = 240;} 806 | + } 807 | + 808 | + if(prev_resolution_w != resolution_to_change_w || prev_resolution_h != resolution_to_change_h) 809 | + { 810 | + if(res_change_count < 2) 811 | + { 812 | + res_change_count += 1; 813 | + printf("PSX GPU - Startup resolution change bypass (%d).\n",res_change_count); 814 | + native_resolution_vcenter = false; // No need Vertical centering for PSX module. 815 | + } 816 | + else{ 817 | + prev_resolution_w = resolution_to_change_w; // will be used in VIDEO.cpp 818 | + prev_resolution_h = resolution_to_change_h; 819 | + printf("PSX - GPU register - resolution change to: %dx%d (V=%d)\n",resolution_to_change_w,resolution_to_change_h,V); 820 | + resolution_to_change = true; // will be reset in VIDEO.cpp 821 | + 822 | + } 823 | + } 824 | +} 825 | +// SLK end 826 | + 827 | void GPU_Init(bool pal_clock_and_tv) 828 | { 829 | static const int8 dither_table[4][4] = 830 | @@ -110,11 +183,25 @@ 831 | { 832 | GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) 833 | hmc_to_visible = 520; 834 | + 835 | + //SLK 836 | + resolution_to_change = true; 837 | + resolution_to_change_w = 640; 838 | + resolution_to_change_h = 480; 839 | + printf("PSX - GPU Init - NTSC mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 840 | + 841 | } 842 | else // PAL clock 843 | { 844 | GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) 845 | hmc_to_visible = 560; 846 | + 847 | + //SLK 848 | + resolution_to_change = true; 849 | + resolution_to_change_w = 640; 850 | + resolution_to_change_h = 576; 851 | + printf("PSX - GPU Init - PAL mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 852 | + 853 | } 854 | 855 | memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); 856 | @@ -905,6 +992,11 @@ 857 | case 0x08: 858 | //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); 859 | DisplayMode = V & 0xFF; 860 | + if(PreviousDisplayMode != DisplayMode) // SLK - Trap GPU resolution change 861 | + { 862 | + PreviousDisplayMode = DisplayMode; 863 | + GPU_NewDisplayMode(V); 864 | + } 865 | break; 866 | 867 | case 0x09: 868 | @@ -1367,6 +1459,16 @@ 869 | int32 fb_x = DisplayFB_XStart * 2; 870 | int32 dx_start = HorizStart, dx_end = HorizEnd; 871 | 872 | + // Hotdog mod - 384 873 | + int32 actualGameBufferWidth = (HorizEnd - HorizStart) / DotClockRatios[dmc]; 874 | + int32 ourBufferWidth = dmw; 875 | + 876 | + int32 leftOffset = (actualGameBufferWidth - ourBufferWidth) / 2; 877 | + //leftOffset *= DotClockRatios[dmc]; // Get back into PSX GPU co-ords. 878 | + leftOffset = std::max(leftOffset, 0); // Make sure not negative 879 | + dx_start += leftOffset; // Offset the PSX buffer to render relative to our frame. 880 | + // 881 | + 882 | dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 883 | dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 884 | 885 | @@ -1376,10 +1478,16 @@ 886 | dx_start = dx_start / DotClockRatios[dmc]; 887 | dx_end = dx_end / DotClockRatios[dmc]; 888 | 889 | - dx_start -= hmc_to_visible / DotClockRatios[dmc]; 890 | - dx_end -= hmc_to_visible / DotClockRatios[dmc]; 891 | - dx_start += 7; 892 | - dx_end += 7; 893 | + // Hotdogmod 894 | + dx_end -= dx_start; 895 | + dx_start = -leftOffset; 896 | + 897 | + // dx_start -= hmc_to_visible / DotClockRatios[dmc]; 898 | + // dx_end -= hmc_to_visible / DotClockRatios[dmc]; 899 | + // dx_start += 7; 900 | + // dx_end += 7; 901 | + // Hotdod mod - end 902 | + 903 | 904 | if(dx_start < 0) 905 | { 906 | diff -Naur -r --no-dereference ./mednafen/src/snes/interface.cpp ./emu4crt/src/snes/interface.cpp 907 | --- ./mednafen/src/snes/interface.cpp 2019-12-24 04:24:48.000000000 -0800 908 | +++ ./emu4crt/src/snes/interface.cpp 2020-01-01 05:54:16.407604969 -0800 909 | @@ -73,6 +73,11 @@ 910 | 911 | static std::vector ColorMap; // [32768] 912 | 913 | +// SLK 914 | +int prev_resolution_w; 915 | +int prev_resolution_h; 916 | +// SLK - end 917 | + 918 | static void BuildColorMap(MDFN_PixelFormat &format, uint8* CustomColorMap) 919 | { 920 | for(int x = 0; x < 32768; x++) 921 | @@ -545,6 +550,23 @@ 922 | MDFNGameInfo->fps = PAL ? 838977920 : 1008307711; 923 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(32040.5); 924 | 925 | + // SLK - init. dynamic display video resolution - progressive by default 926 | + printf("SNES Interface - Regional mode: %s \n",(PAL ? "PAL" : "NTSC")); 927 | + if(PAL) 928 | + { 929 | + resolution_to_change_h = 288; 930 | + } 931 | + else 932 | + { 933 | + printf(" Video mode set to 256 x 240\n"); 934 | + resolution_to_change_h = 240; 935 | + } 936 | + resolution_to_change_w = 256; 937 | + resolution_to_change = true; 938 | + prev_resolution_w = resolution_to_change_w; 939 | + prev_resolution_h = resolution_to_change_h; 940 | + // SLK - end 941 | + 942 | if(!snsf_loader) 943 | { 944 | EnableHBlend = MDFN_GetSettingB("snes.h_blend"); 945 | @@ -889,6 +911,32 @@ 946 | bSNES_v059::system.run_mednafen_custom(); 947 | bSNES_v059::ppu.enable_renderer(true); 948 | 949 | + // SLK - guess SNES active resolution 950 | + //printf("SNES Interface - Emulate - %dx%d - %d,%d\n",tdr->w,tdr->h,tdr->x,tdr->y); 951 | + if(tdr->h > 10 && tdr->w > 10 && tdr->w != prev_resolution_w) 952 | + { 953 | + resolution_to_change = true; 954 | + resolution_to_change_w = tdr->w; 955 | + } 956 | + if(tdr->h > 10 && tdr->w > 10 && tdr->h != prev_resolution_h) 957 | + { 958 | + resolution_to_change = true; 959 | + if(tdr->h <= 400) 960 | + { 961 | + resolution_to_change_h = bSNES_v059::system.region() ? 288 : 240; 962 | + } 963 | + else 964 | + { 965 | + resolution_to_change_h = bSNES_v059::system.region() ? 576 : 480; 966 | + } 967 | + } 968 | + if(resolution_to_change) 969 | + { 970 | + //printf("SNES - Interface - Resolution change detected: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 971 | + prev_resolution_w = resolution_to_change_w; 972 | + prev_resolution_h = tdr->h; 973 | + } 974 | + // SLK - end 975 | 976 | // 977 | // Blank out any missed lines(for e.g. display height change with PAL emulation) 978 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_common.h ./emu4crt/src/snes_faust/ppu_common.h 979 | --- ./mednafen/src/snes_faust/ppu_common.h 2019-12-24 04:24:48.000000000 -0800 980 | +++ ./emu4crt/src/snes_faust/ppu_common.h 2020-01-01 15:01:01.392029912 -0800 981 | @@ -23,3 +23,7 @@ 982 | void PPU_PokeOAMHI(uint32 addr, uint8 val) MDFN_COLD; 983 | void PPU_SetRegister(const unsigned id, const uint32 value) MDFN_COLD; 984 | 985 | +// SLK 986 | +//int prev_resolution_w; 987 | +//int prev_resolution_h; 988 | +// SLK 989 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mt.cpp ./emu4crt/src/snes_faust/ppu_mt.cpp 990 | --- ./mednafen/src/snes_faust/ppu_mt.cpp 2019-12-24 04:24:48.000000000 -0800 991 | +++ ./emu4crt/src/snes_faust/ppu_mt.cpp 2020-01-01 14:56:52.304295037 -0800 992 | @@ -43,6 +43,12 @@ 993 | namespace PPU_MT 994 | { 995 | 996 | +// SLK 997 | +int prev_resolution_w; 998 | +int prev_resolution_h; 999 | +// SLK 1000 | + 1001 | + 1002 | static struct 1003 | { 1004 | uint32 lastts; 1005 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mtrender.cpp ./emu4crt/src/snes_faust/ppu_mtrender.cpp 1006 | --- ./mednafen/src/snes_faust/ppu_mtrender.cpp 2019-12-24 04:24:48.000000000 -0800 1007 | +++ ./emu4crt/src/snes_faust/ppu_mtrender.cpp 2020-01-01 14:57:23.375643922 -0800 1008 | @@ -23,6 +23,10 @@ 1009 | #include "ppu.h" 1010 | #include "ppu_mtrender.h" 1011 | 1012 | +// SLK 1013 | +// #include 1014 | +// SLK end 1015 | + 1016 | #include 1017 | #include 1018 | 1019 | @@ -45,6 +49,12 @@ 1020 | namespace PPU_MTRENDER 1021 | { 1022 | 1023 | +// SLK 1024 | +int prev_resolution_w; 1025 | +int prev_resolution_h; 1026 | +// SLK 1027 | + 1028 | + 1029 | PPU_S PPU; 1030 | 1031 | #include "ppu_render_common.inc" 1032 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_render_common.inc ./emu4crt/src/snes_faust/ppu_render_common.inc 1033 | --- ./mednafen/src/snes_faust/ppu_render_common.inc 2019-12-24 04:24:48.000000000 -0800 1034 | +++ ./emu4crt/src/snes_faust/ppu_render_common.inc 2020-01-01 14:48:50.555151900 -0800 1035 | @@ -1621,6 +1621,16 @@ 1036 | T* const out_target = es->surface->pix() + out_line * es->surface->pitchinpix; 1037 | const uint32 w = ((BGMode & 0x7) == 0x5 || (BGMode & 0x7) == 0x6 || (ScreenMode & 0x08)) ? 512 : 256; 1038 | 1039 | +// SLK 1040 | + if(w != prev_resolution_w) 1041 | + { 1042 | + resolution_to_change_w = w; 1043 | + prev_resolution_w = w; 1044 | + resolution_to_change = true; 1045 | + } 1046 | +// SLK - end 1047 | + 1048 | + 1049 | es->LineWidths[out_line] = w; 1050 | // 1051 | LineTarget++; 1052 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_st.cpp ./emu4crt/src/snes_faust/ppu_st.cpp 1053 | --- ./mednafen/src/snes_faust/ppu_st.cpp 2019-12-24 04:24:48.000000000 -0800 1054 | +++ ./emu4crt/src/snes_faust/ppu_st.cpp 2020-01-01 14:56:43.112533920 -0800 1055 | @@ -34,6 +34,10 @@ 1056 | #include "input.h" 1057 | #include "cart.h" 1058 | 1059 | +// SLK 1060 | +#include 1061 | +// SLK end 1062 | + 1063 | #include 1064 | #include 1065 | 1066 | @@ -56,6 +60,11 @@ 1067 | namespace PPU_ST 1068 | { 1069 | 1070 | +// SLK 1071 | +int prev_resolution_w; 1072 | +int prev_resolution_h; 1073 | +// SLK 1074 | + 1075 | struct PPU_S 1076 | { 1077 | uint32 lastts; 1078 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/snes.cpp ./emu4crt/src/snes_faust/snes.cpp 1079 | --- ./mednafen/src/snes_faust/snes.cpp 2019-12-24 04:24:48.000000000 -0800 1080 | +++ ./emu4crt/src/snes_faust/snes.cpp 2020-01-01 14:50:31.525517853 -0800 1081 | @@ -43,6 +43,7 @@ 1082 | static MemoryStream* SpecExSS = NULL; 1083 | static int32 SpecExAudioExpected; 1084 | 1085 | + 1086 | struct ReadPatchInfoStruct 1087 | { 1088 | bool operator<(const ReadPatchInfoStruct& o) const 1089 | @@ -604,6 +605,8 @@ 1090 | } 1091 | } 1092 | 1093 | + 1094 | + 1095 | DMA_Init(); 1096 | // 1097 | // 1098 | @@ -617,6 +620,9 @@ 1099 | const unsigned region = MDFN_GetSettingUI("snes_faust.region"); 1100 | bool IsPAL, IsPALPPUBit; 1101 | 1102 | + 1103 | + 1104 | + 1105 | if(snsf_loader) 1106 | { 1107 | uint8* const cart_ram = CART_GetRAMPointer(); 1108 | @@ -671,6 +677,23 @@ 1109 | } 1110 | // 1111 | // 1112 | + 1113 | +// SLK - init. dynamic display video resolution - progressive by default 1114 | + printf("SNES FAUST snes - Regional mode: %s \n",(IsPAL ? "PAL" : "NTSC")); 1115 | + if(IsPAL) 1116 | + { 1117 | + resolution_to_change_h = 288; 1118 | + } 1119 | + else 1120 | + { 1121 | + printf(" Video mode set to 256 x 240\n"); 1122 | + resolution_to_change_h = 240; 1123 | + } 1124 | + resolution_to_change_w = 256; 1125 | + resolution_to_change = true; 1126 | + // SLK - end 1127 | + 1128 | + 1129 | INPUT_Init(); 1130 | { 1131 | const bool mte[2] = { MDFN_GetSettingB("snes_faust.input.sport1.multitap"), MDFN_GetSettingB("snes_faust.input.sport2.multitap") }; 1132 | diff -Naur -r --no-dereference ./mednafen/src/ss/vdp2_render.cpp ./emu4crt/src/ss/vdp2_render.cpp 1133 | --- ./mednafen/src/ss/vdp2_render.cpp 2019-12-24 04:24:48.000000000 -0800 1134 | +++ ./emu4crt/src/ss/vdp2_render.cpp 2019-12-26 07:31:34.355158000 -0800 1135 | @@ -145,6 +145,14 @@ 1136 | static uint8 LineColorCCRatio; 1137 | static uint8 BackCCRatio; 1138 | 1139 | +//SLK 1140 | +static uint8 prev_InterlaceMode = 0; 1141 | +static uint8 prev_HRes = 0; 1142 | +static uint8 prev_VRes = 0; 1143 | +static bool prev_BorderMode = 0; 1144 | +// SLK end 1145 | + 1146 | + 1147 | // 1148 | static struct 1149 | { 1150 | @@ -550,6 +558,39 @@ 1151 | InterlaceMode = (V >> 6) & 0x3; 1152 | VRes = (V >> 4) & 0x3; 1153 | HRes = (V >> 0) & 0x7; 1154 | + // SLK 1155 | + if(InterlaceMode != prev_InterlaceMode || HRes != prev_HRes) 1156 | + { 1157 | + printf("VDP2 Render - Television mode changed: %d\n",V); 1158 | + printf(" BorderMode: %d\n",BorderMode); 1159 | + printf(" PAL: %d\n",PAL); 1160 | + printf(" InterlaceMode: %d\n",InterlaceMode); 1161 | + printf(" VRes: %d\n",VRes); 1162 | + printf(" HRes: %d\n",HRes); 1163 | + prev_BorderMode = BorderMode; 1164 | + prev_InterlaceMode = InterlaceMode; 1165 | + prev_VRes = VRes; 1166 | + prev_HRes = HRes; 1167 | + // HRES 1168 | + switch(HRes){ 1169 | + case 0: 1170 | + resolution_to_change_w = 320; 1171 | + break; 1172 | + case 1: 1173 | + resolution_to_change_w = 352; 1174 | + break; 1175 | + case 2: 1176 | + resolution_to_change_w = 640; 1177 | + break; 1178 | + case 3: 1179 | + resolution_to_change_w = 704; 1180 | + break; 1181 | + } 1182 | + if(InterlaceMode >= 2){resolution_to_change_h = PAL ? 576 : 480;} else {resolution_to_change_h = PAL ? 288 : 240;} 1183 | + printf("SS - VDP2 Render - TV mode set to %dx%d",resolution_to_change_w,resolution_to_change_h); 1184 | + resolution_to_change = true; // Flag for video resolution change by VIDEO.cpp/MAIN.cpp 1185 | + } 1186 | + // SLK - end 1187 | break; 1188 | 1189 | case 0x02: 1190 | @@ -3295,12 +3336,20 @@ 1191 | { 1192 | gi->nominal_width = (ShowHOverscan ? 365 : 354); 1193 | gi->fb_height = 576; 1194 | + resolution_to_change_h = 288; // SLK - init crt mode 1195 | } 1196 | else 1197 | { 1198 | gi->nominal_width = (ShowHOverscan ? 302 : 292); 1199 | gi->fb_height = 480; 1200 | + resolution_to_change_h = 240; // SLK - init crt mode 1201 | } 1202 | + // SLK 1203 | + resolution_to_change_w = 320; 1204 | + resolution_to_change = true; // SLK - init crt mode 1205 | + // SLK - end 1206 | + 1207 | + 1208 | gi->nominal_height = LineVisLast + 1 - LineVisFirst; 1209 | 1210 | gi->lcm_width = (ShowHOverscan? 10560 : 10240); 1211 | diff -Naur -r --no-dereference ./mednafen/src/state.cpp ./emu4crt/src/state.cpp 1212 | --- ./mednafen/src/state.cpp 2019-12-24 04:24:48.000000000 -0800 1213 | +++ ./emu4crt/src/state.cpp 2019-12-26 07:31:35.795145000 -0800 1214 | @@ -470,6 +470,14 @@ 1215 | neowidth = MDFNGameInfo->nominal_width; 1216 | neoheight = MDFNGameInfo->nominal_height; 1217 | 1218 | + // SLK - Approximation to prevent SaveState snapshot corruption 1219 | + if(use_super_resolution) 1220 | + { 1221 | + neowidth = resolution_to_change_w; 1222 | + neoheight = DisplayRect->h; 1223 | + } 1224 | + // SLK - end 1225 | + 1226 | if(LineWidths[0] != ~0) 1227 | { 1228 | int32 first_w = LineWidths[DisplayRect->y]; 1229 | @@ -857,7 +865,9 @@ 1230 | MDFN_Error* me = dynamic_cast(&e); 1231 | 1232 | if(!fname && !suffix) 1233 | - MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1234 | + // SLK 1235 | + // MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1236 | + MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d not found."), CurrentState); // SLK - shorten message to fit low-res rendering 1237 | else 1238 | { 1239 | // FIXME: Autosave kludgery, refactor interfaces in the future to make cleaner. 1240 | -------------------------------------------------------------------------------- /patches/mednafen-1.24.0-UNSTABLE-emu4crt-A10.patch: -------------------------------------------------------------------------------- 1 | diff -Naur -r --no-dereference ./mednafen/configure ./emu4crt/configure 2 | --- ./mednafen/configure 2019-12-24 04:24:48.000000000 -0800 3 | +++ ./emu4crt/configure 2019-12-26 07:29:42.895790000 -0800 4 | @@ -18085,7 +18085,8 @@ 5 | fi 6 | 7 | 8 | - LIBS="-mconsole -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 9 | +/* SLK - switch -mconsole */ 10 | + LIBS="-mwindows -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 11 | CPPFLAGS="-D_LFS64_LARGEFILE=1 $CPPFLAGS" 12 | elif expr x"$host" : 'x.*djgpp' > /dev/null; then 13 | 14 | diff -Naur -r --no-dereference ./mednafen/Documentation/modules.def ./emu4crt/Documentation/modules.def 15 | --- ./mednafen/Documentation/modules.def 2019-12-24 04:24:48.000000000 -0800 16 | +++ ./emu4crt/Documentation/modules.def 2020-01-15 13:00:16.408693403 -0800 17 | @@ -1,4 +1,4 @@ 18 | -1.24.0-UNSTABLE 19 | +1.24.0-UNSTABLE-emu4crt-A10 20 | apple2 21 | Apple II/II+ 22 | 250 23 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.cpp ./emu4crt/src/drivers/main.cpp 24 | --- ./mednafen/src/drivers/main.cpp 2019-12-24 04:24:48.000000000 -0800 25 | +++ ./emu4crt/src/drivers/main.cpp 2020-01-14 14:27:35.903453362 -0800 26 | @@ -273,6 +273,7 @@ 27 | MDFNGI *CurGame=NULL; 28 | 29 | 30 | + 31 | #ifdef WIN32 32 | static std::string GetModuleFileName_UTF8(HMODULE hModule) 33 | { 34 | @@ -287,6 +288,47 @@ 35 | return UTF16_to_UTF8(&path[0], nullptr, true); 36 | } 37 | 38 | + 39 | +static bool HandleConsoleMadness(void) // SLK - enforce stdout.txt & stderr.txt out to files 40 | +{ 41 | + bool ret; 42 | + if(AllocConsole()) 43 | + { 44 | + HWND cwin = GetConsoleWindow(); 45 | + ShowWindow(cwin, SW_HIDE); 46 | + 47 | + freopen("CONOUT$", "w", stdout); 48 | + freopen("CONOUT$", "w", stderr); 49 | + 50 | + SetConsoleOutputCP(65001); // UTF-8 51 | + 52 | + std::string path; 53 | + size_t catpos; // Meow meow. 54 | + path = GetModuleFileName_UTF8(NULL); 55 | + if((catpos = path.find_last_of('\\')) != std::string::npos) path.resize(catpos + 1); 56 | + const std::u16string stdout_path = UTF8_to_UTF16(path + "stdout.txt", nullptr, true); 57 | + const std::u16string stderr_path = UTF8_to_UTF16(path + "stderr.txt", nullptr, true); 58 | + int new_stdout = -1; 59 | + int new_stderr = -1; 60 | + new_stdout = _wopen((const wchar_t*)stdout_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 61 | + new_stderr = _wopen((const wchar_t*)stderr_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 62 | + 63 | + fflush(stdout); 64 | + fflush(stderr); 65 | + 66 | + dup2(new_stdout, fileno(stdout)); 67 | + dup2(new_stderr, fileno(stderr)); 68 | + 69 | + close(new_stdout); 70 | + close(new_stderr); 71 | + 72 | + } 73 | + ret = false; 74 | + return ret; 75 | +} 76 | + 77 | +/* // SLK - Disable native redirection functions due to switch back to windows application 78 | + 79 | // returns 1 if redirected, 0 if not redirected due to error, -1 if not redirected due to env variable 80 | static int RedirectSTDxxx(void) 81 | { 82 | @@ -398,6 +440,8 @@ 83 | 84 | return ret; 85 | } 86 | +*/ 87 | + 88 | #endif 89 | 90 | void Mednafen::MDFND_OutputNotice(MDFN_NoticeType t, const char* s) noexcept 91 | @@ -1034,6 +1078,10 @@ 92 | } 93 | 94 | static volatile unsigned NeedVideoSync = 0; 95 | +//SLK 96 | +static volatile unsigned NeedResolutionChange = 0; // trigger to switch window/fullscreen resolution 97 | +//SLK end 98 | + 99 | static int GameLoop(void *arg); 100 | int volatile GameThreadRun = 0; 101 | static bool MDFND_Update(int WhichVideoBuffer, int16 *Buffer, int Count); 102 | @@ -1267,56 +1315,84 @@ 103 | { 104 | while(GameThreadRun) 105 | { 106 | - int16 *sound; 107 | - int32 ssize; 108 | - bool fskip; 109 | - 110 | + //SLK - trap change resolution request 111 | + if(resolution_to_change) 112 | + { 113 | + if(use_native_resolution) 114 | + { 115 | + if((current_resolution_w != resolution_to_change_w) || (current_resolution_h != resolution_to_change_h)) 116 | + { 117 | + printf("MAIN - native resolution to switch!\n"); 118 | + NeedResolutionChange++; 119 | + } 120 | + else {printf("MAIN - resolution change bypassed\n");} 121 | + } 122 | + if(use_super_resolution) 123 | + { 124 | + if(resolution_to_change_h != current_resolution_h) 125 | + { 126 | + printf("MAIN - Super resolution to switch: 2560 x %d\n", resolution_to_change_h); 127 | + NeedResolutionChange++; 128 | + } 129 | + else {printf("MAIN - Super resolution change bypassed\n");} 130 | + } 131 | + resolution_to_change = false; 132 | + } 133 | + // SLK - end 134 | + 135 | + int16 *sound; 136 | + int32 ssize; 137 | + bool fskip; 138 | + 139 | /* If we requested a new video mode, wait until it's set before calling the emulation code again. 140 | */ 141 | - while(NeedVideoSync) 142 | - { 143 | - if(!GameThreadRun) return(1); // Might happen if video initialization failed 144 | - Time::SleepMS(2); 145 | - } 146 | 147 | - if(Sound_NeedReInit()) 148 | - GT_ReinitSound(); 149 | + //SLK 150 | + while(NeedVideoSync) 151 | + //while(NeedVideoSync || NeedResolutionChange) // need to wait during resolution change ??? 152 | + //SLK 153 | + { 154 | + if(!GameThreadRun) return(1); // Might happen if video initialization failed 155 | + Time::SleepMS(2); 156 | + } 157 | + if(Sound_NeedReInit()) 158 | + GT_ReinitSound(); 159 | 160 | - if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 161 | - ers.SetETtoRT(); 162 | - // 163 | - // 164 | - fskip = ers.NeedFrameSkip(); 165 | - fskip &= MDFN_GetSettingB("video.frameskip"); 166 | - fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 167 | - fskip |= (bool)NoWaiting; 168 | + if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 169 | + ers.SetETtoRT(); 170 | + // 171 | + // 172 | + fskip = ers.NeedFrameSkip(); 173 | + fskip &= MDFN_GetSettingB("video.frameskip"); 174 | + fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 175 | + fskip |= (bool)NoWaiting; 176 | 177 | - //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 178 | + //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 179 | 180 | - NeedFrameAdvance = false; 181 | - // 182 | - // 183 | - SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 184 | + NeedFrameAdvance = false; 185 | + // 186 | + // 187 | + SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 188 | 189 | - // 190 | - // 191 | - // 192 | - EmulateSpecStruct espec; 193 | + // 194 | + // 195 | + // 196 | + EmulateSpecStruct espec; 197 | 198 | - espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 199 | - espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 200 | - espec.skip = fskip; 201 | - espec.soundmultiplier = CurGameSpeed; 202 | - espec.NeedRewind = DNeedRewind; 203 | - 204 | - espec.SoundRate = Sound_GetRate(); 205 | - espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 206 | - espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 207 | + espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 208 | + espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 209 | + espec.skip = fskip; 210 | + espec.soundmultiplier = CurGameSpeed; 211 | + espec.NeedRewind = DNeedRewind; 212 | 213 | - if(MDFN_UNLIKELY(StateRCTest)) 214 | - { 215 | - // Note: Won't work correctly with modules that do mid-sync. 216 | - EmulateSpecStruct estmp = espec; 217 | + espec.SoundRate = Sound_GetRate(); 218 | + espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 219 | + espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 220 | + 221 | + if(MDFN_UNLIKELY(StateRCTest)) 222 | + { 223 | + // Note: Won't work correctly with modules that do mid-sync. 224 | + EmulateSpecStruct estmp = espec; 225 | 226 | MemoryStream state0(524288); 227 | MemoryStream state1(524288); 228 | @@ -1334,19 +1410,19 @@ 229 | 230 | if(!(state1.map_size() == state2.map_size() && !memcmp(state1.map() + 32, state2.map() + 32, state1.map_size() - 32))) 231 | { 232 | - FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 233 | - FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 234 | + FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 235 | + FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 236 | 237 | - sd0.write(state1.map(), state1.map_size()); 238 | - sd1.write(state2.map(), state2.map_size()); 239 | - sd0.close(); 240 | - sd1.close(); 241 | - //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 242 | - abort(); 243 | + sd0.write(state1.map(), state1.map_size()); 244 | + sd1.write(state2.map(), state2.map_size()); 245 | + sd0.close(); 246 | + sd1.close(); 247 | + //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 248 | + abort(); 249 | } 250 | - } 251 | - else 252 | - MDFNI_Emulate(&espec); 253 | + } 254 | + else 255 | + MDFNI_Emulate(&espec); 256 | 257 | if(MDFN_UNLIKELY(StateSLSTest)) 258 | { 259 | @@ -2149,7 +2225,7 @@ 260 | } 261 | 262 | #ifdef WIN32 263 | - HandleConsoleMadness(); 264 | + HandleConsoleMadness(); // SLK 265 | #endif 266 | 267 | //ThreadTest(); 268 | @@ -2424,12 +2500,20 @@ 269 | PumpWrap(); 270 | 271 | if(MDFN_UNLIKELY(NeedVideoSync)) 272 | - { 273 | - Video_Sync(CurGame); 274 | - PumpWrap(); 275 | - // 276 | - NeedVideoSync = 0; 277 | - } 278 | + { 279 | + Video_Sync(CurGame); 280 | + PumpWrap(); 281 | + NeedVideoSync = 0; 282 | + } 283 | + // SLK 284 | + if(MDFN_UNLIKELY(NeedResolutionChange)) 285 | + { 286 | + Video_ChangeResolution(CurGame, resolution_to_change_w, resolution_to_change_h); 287 | + // ??? PumpWrap(); 288 | + NeedResolutionChange = 0; 289 | + printf("MAIN - End of resolution change\n"); 290 | + } 291 | + // SLK END 292 | 293 | if(NeededWMInputBehavior_Dirty) 294 | { 295 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.h ./emu4crt/src/drivers/main.h 296 | --- ./mednafen/src/drivers/main.h 2019-12-24 04:24:48.000000000 -0800 297 | +++ ./emu4crt/src/drivers/main.h 2020-01-11 19:04:50.854434506 -0800 298 | @@ -70,7 +70,6 @@ 299 | bool GT_ReinitVideo(void); 300 | bool GT_ReinitSound(void); 301 | 302 | - 303 | void BuildSystemSetting(MDFNSetting *setting, const char *system_name, const char *name, const char *description, const char *description_extra, MDFNSettingType type, 304 | const char *default_value, const char *minimum = NULL, const char *maximum = NULL, 305 | bool (*validate_func)(const char *name, const char *value) = NULL, void (*ChangeNotification)(const char *name) = NULL, 306 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video.cpp ./emu4crt/src/drivers/video.cpp 307 | --- ./mednafen/src/drivers/video.cpp 2019-12-24 04:24:48.000000000 -0800 308 | +++ ./emu4crt/src/drivers/video.cpp 2020-01-14 14:24:39.109233930 -0800 309 | @@ -105,6 +105,16 @@ 310 | VDRIVER__COUNT 311 | }; 312 | 313 | +// SLK 314 | +static int _resolution_switch; 315 | +enum 316 | +{ 317 | + RES_STATIC = 0, 318 | + RES_NATIVE = 1, 319 | + RES_SUPER = 2 320 | +}; 321 | +// SLK - end 322 | + 323 | enum 324 | { 325 | NTVB_NONE = 0, 326 | @@ -146,6 +156,17 @@ 327 | { NULL, 0 }, 328 | }; 329 | 330 | +// SLK - custom setting 331 | +static const MDFNSetting_EnumList Resolution_Switch[] = 332 | +{ 333 | + // Legacy: 334 | + { "0", RES_STATIC}, 335 | + { "native", RES_NATIVE, "Native resolution", gettext_noop("Use emulated system native resolution.") }, 336 | + { "super", RES_SUPER, "Super resolution", gettext_noop("Use super resolutions") }, 337 | + { NULL, 0 }, 338 | +}; 339 | +// SLK - end 340 | + 341 | static const MDFNSetting GlobalVideoSettings[] = 342 | { 343 | { "video.driver", MDFNSF_NOFLAGS, gettext_noop("Video output driver."), NULL, MDFNST_ENUM, "default", NULL, NULL, NULL, NULL, VDriver_List }, 344 | @@ -161,6 +182,11 @@ 345 | MDFNST_BOOL, "1" }, 346 | 347 | { "video.disable_composition", MDFNSF_NOFLAGS, gettext_noop("Attempt to disable desktop composition."), gettext_noop("Currently, this setting only has an effect on Windows Vista and Windows 7(and probably the equivalent server versions as well)."), MDFNST_BOOL, "1" }, 348 | + 349 | + // SLK - admit new parameter 350 | + { "video.resolution_switch", MDFNSF_NOFLAGS, gettext_noop("Video resolution switch (0, native or super)."), NULL, MDFNST_ENUM, "0", NULL, NULL, NULL, NULL, Resolution_Switch}, 351 | + // SLK - end 352 | + 353 | }; 354 | 355 | static const MDFNSetting_EnumList StretchMode_List[] = 356 | @@ -746,6 +772,165 @@ 357 | SetMode(new_mode); 358 | #endif 359 | 360 | + 361 | +// SLK 362 | +void Video_ChangeResolution(MDFNGI *gi, int w, int h) 363 | +{ 364 | + printf("VIDEO - Video_ChangeResolution - Requested video mode: %d x %d\n", w, h); 365 | + SMRect.w = w; 366 | + if(use_super_resolution) w = 2560; 367 | + 368 | + switch(h){ 369 | + case 240:SMDRect.y = h - SMDRect.h - 18; 370 | + break; 371 | + case 288:SMDRect.y = h - SMDRect.h - 32; 372 | + break; 373 | + case 480:SMDRect.y = h - SMDRect.h - 32; 374 | + break; 375 | + case 576:SMDRect.y = h - SMDRect.h - 64; 376 | + } 377 | + 378 | + if(SMSurface) 379 | + { 380 | + MDFN_PixelFormat SMFormat = SMSurface->format; 381 | + delete SMSurface; 382 | + SMSurface = nullptr; 383 | + SMSurface = new MDFN_Surface(NULL, SMRect.w, SMRect.h, SMRect.w, SMFormat); 384 | + } 385 | +/* TODO - rebuild HelpSurface on resolution change 386 | + if(HelpSurface) 387 | + { 388 | + delete HelpSurface; 389 | + HelpSurface = nullptr; 390 | + } 391 | +*/ 392 | + 393 | +// TODO: clean unwanted and duplicate code 394 | + if(video_settings.fullscreen == 0) 395 | + { 396 | + printf(" Video mode: WINDOWED\n"); 397 | + 398 | + SDL_SetWindowSize(window, w, h); 399 | + video_settings.xres = w; 400 | + video_settings.yres = h; 401 | + VideoGI->nominal_width = w; 402 | + screen_dest_rect.w = screen_w = w; 403 | + screen_dest_rect.h = screen_h = h; 404 | + screen_dest_rect.x = 0; 405 | + screen_dest_rect.y = 0; 406 | + int x, y; 407 | + SDL_GetWindowPosition(window, &x, &y); 408 | + SDL_PumpEvents(); 409 | + SDL_SetWindowPosition(window, x, y); 410 | + ogl_blitter->SetViewport(w, h); 411 | + current_resolution_h = h; 412 | + current_resolution_w = w; 413 | + } 414 | + else 415 | + { 416 | + printf(" Video mode: FULLSCREEN\n"); 417 | + 418 | + SDL_DisplayMode current; 419 | + SDL_DisplayMode mode; 420 | + SDL_DisplayMode trymode; 421 | + int displayIndex; 422 | + 423 | + displayIndex = SDL_GetWindowDisplayIndex(window); 424 | + if(displayIndex < 0) 425 | + { 426 | + printf(" ERROR Could not get screen index: %s\n", SDL_GetError()); 427 | + return; 428 | + } 429 | + else 430 | + { 431 | + printf(" Screen index: %d\n",displayIndex); 432 | + } 433 | + 434 | + if(SDL_GetCurrentDisplayMode(displayIndex, ¤t) != 0) 435 | + { 436 | + printf(" Could not get display mode for video display %d: %s\n", displayIndex, SDL_GetError()); 437 | + } 438 | + else 439 | + { 440 | + printf(" Display #%d: Current display mode is %dx%dpx @ %dhz.\n", displayIndex, current.w, current.h, current.refresh_rate); 441 | + trymode.w = w; 442 | + trymode.h = h; 443 | + trymode.refresh_rate = 0; 444 | + 445 | + if (SDL_GetClosestDisplayMode(displayIndex, &trymode, &mode) == NULL) 446 | + { 447 | + printf(" No suitable display mode was found, %s\n",SDL_GetError()); 448 | + } 449 | + else 450 | + { 451 | + printf(" Received: \t%dx%dpx @ %dhz \n", mode.w, mode.h, mode.refresh_rate); 452 | +#ifdef WIN32 453 | + // Use Win32 API for resolution chang 454 | + Video_WinSetVideoMode(mode.w,mode.h); 455 | + SDL_SetWindowSize(window, w, h); 456 | + video_settings.xres = w; 457 | + video_settings.yres = h; 458 | + screen_dest_rect.x = 0; 459 | + screen_dest_rect.y = 0; 460 | + screen_dest_rect.w = w; 461 | + screen_dest_rect.h = h; 462 | + screen_w = w; 463 | + screen_h = h; 464 | + ogl_blitter->SetViewport(screen_w, screen_h); 465 | + current_resolution_h = h; 466 | + current_resolution_w = w; 467 | +#else 468 | + // Use SDL video change function - slower 469 | + if(SDL_SetWindowDisplayMode(window, &mode) < 0) 470 | + { 471 | + printf("ERROR - SDL_SetWindowDisplayMode: '%s'\n", SDL_GetError()); 472 | + } 473 | + else 474 | + { 475 | + SDL_SetWindowSize(window, w, h); 476 | + video_settings.xres = w; 477 | + video_settings.yres = h; 478 | + VideoGI->nominal_width = w; 479 | + screen_w = w; 480 | + screen_h = h; 481 | + // screen = SDL_GetWindowSurface(window); 482 | + screen_dest_rect.x = 0; 483 | + screen_dest_rect.y = 0; 484 | + screen_dest_rect.w = w; 485 | + screen_dest_rect.h = h; 486 | + //SDL_GetWindowPosition(window, &x, &y); 487 | + //SDL_PumpEvents(); 488 | + //SDL_SetWindowPosition(window, x, y); 489 | + ogl_blitter->SetViewport(screen_w, screen_h); 490 | + current_resolution_h = h; 491 | + current_resolution_w = w; 492 | + } 493 | +#endif 494 | + } 495 | + printf("VIDEO - Video_ChangeResolution done"); 496 | + } 497 | + } 498 | +} 499 | + 500 | +#ifdef WIN32 501 | +void Video_WinSetVideoMode(int iWidth, int iHeight) 502 | +{ 503 | + DEVMODE Mode; 504 | + printf("EnumDisplaySettings return: %ld\n",EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Mode)); 505 | + 506 | + //Mode.dmBitsPerPel = iBpp; 507 | + 508 | + Mode.dmPelsWidth = iWidth; 509 | + Mode.dmPelsHeight = iHeight; 510 | + Mode.dmSize = sizeof(Mode); 511 | + Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; 512 | + 513 | + printf("ChangeDisplaySettings return: %ld\n",ChangeDisplaySettings(&Mode, CDS_FULLSCREEN)); 514 | + 515 | +}; 516 | +#endif 517 | +// SLK - end 518 | + 519 | void Video_Sync(MDFNGI *gi) 520 | { 521 | MDFNI_printf(_("Initializing video...\n")); 522 | @@ -844,6 +1029,41 @@ 523 | 524 | video_settings.shader = (ShaderType)MDFN_GetSettingI(snp + "shader"); 525 | video_settings.shader_str = MDFN_GetSettingS(snp + "shader"); 526 | + 527 | + // SLK - set video settings - disable some options in conflict with native resolution 528 | + _resolution_switch = MDFN_GetSettingI("video.resolution_switch"); 529 | + if(_resolution_switch) 530 | + { 531 | + if(_resolution_switch == RES_NATIVE) // Native Res 532 | + { 533 | + use_native_resolution = true; 534 | + printf("### VIDEO Native resolution init - set to %dx%d\n",resolution_to_change_w,resolution_to_change_h); 535 | + video_settings.xres = resolution_to_change_w; // for fullscreen mode 536 | + VideoGI->nominal_width = resolution_to_change_w; // for windowed mode 537 | + video_settings.xscale = 1; 538 | + video_settings.xscalefs = 1; 539 | + video_settings.yscalefs = 1; 540 | + video_settings.stretch = 0; 541 | + 542 | + } 543 | + if(_resolution_switch == RES_SUPER) 544 | + { 545 | + use_super_resolution = true; 546 | + printf("### VIDEO Super resolution init - set to 2560x%d\n",resolution_to_change_h); 547 | + video_settings.xres = current_resolution_w = 2560; // for fullscreen mode 548 | + VideoGI->nominal_width = 2560; // for windowed mode 549 | + video_settings.xscale = 1; 550 | + video_settings.xscalefs = 1; 551 | + video_settings.yscalefs = 1; 552 | + video_settings.stretch = 0; 553 | + } 554 | + video_settings.yres = current_resolution_h = resolution_to_change_h; // for fullscreen mode 555 | + VideoGI->nominal_height = resolution_to_change_h; // for windowed mode 556 | + video_settings.yscale = 1; 557 | + video_settings.videoip = 0; 558 | + video_settings.shader = SHADER_NONE; 559 | + } 560 | + 561 | // 562 | // 563 | if(0) 564 | @@ -1238,11 +1458,44 @@ 565 | SMRect.y = 0; 566 | SMRect.w = screen_w; 567 | 568 | - SMDRect.w = SMRect.w * xmu; 569 | + // SLK - Set OSD message rendering rect. 570 | + if(use_super_resolution) // enlarge OSD message in super resolution mode 571 | + { 572 | + SMDRect.w = SMRect.w * xmu; 573 | + printf("VIDEO - Init : SMRect.w: %d xmu: %d\n",SMRect.w,xmu); 574 | + } 575 | + else 576 | + { 577 | + SMDRect.w = SMRect.w * xmu; 578 | + } 579 | + // SLK - end 580 | + 581 | + //SMDRect.w = SMRect.w * xmu; 582 | SMDRect.h = SMRect.h * ymu; 583 | SMDRect.x = (screen_w - SMDRect.w) / 2; 584 | - SMDRect.y = screen_h - SMDRect.h; 585 | + // SMDRect.y = screen_h - SMDRect.h; 586 | 587 | + // SLK - Vertical offset for OSD messages 588 | + if(use_native_resolution || use_super_resolution) 589 | + { 590 | + switch(screen_h){ 591 | + case 240:SMDRect.y = screen_h - SMDRect.h - 18; 592 | + break; 593 | + case 288:SMDRect.y = screen_h - SMDRect.h - 32; 594 | + break; 595 | + case 480:SMDRect.y = screen_h - SMDRect.h - 32; 596 | + break; 597 | + case 576:SMDRect.y = screen_h - SMDRect.h - 64; 598 | + break; 599 | + default:SMDRect.y = screen_h - SMDRect.h * xmu; // TODO: ??? 600 | + } 601 | + } 602 | + else 603 | + { 604 | + SMDRect.y = screen_h - SMDRect.h; 605 | + } 606 | + // SLK - end 607 | + 608 | if(SMDRect.x < 0) 609 | { 610 | SMRect.w += SMDRect.x * 2 / xmu; 611 | @@ -1645,9 +1898,21 @@ 612 | src_rect.w = DisplayRect->w; 613 | src_rect.y = DisplayRect->y; 614 | src_rect.h = DisplayRect->h; 615 | + 616 | + 617 | 618 | if(LineWidths[0] == ~0) // Skip multi line widths code? 619 | { 620 | + // SLK - blit for: NES 621 | + //printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 622 | + //printf(" Dest: %dx%d - %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 623 | + // src_rect.y = (resolution_to_change_h - src_rect.h) / 2 ; //SLK 624 | + if(use_native_resolution || use_super_resolution) 625 | + { 626 | + screen_dest_rect.y = (resolution_to_change_h - src_rect.h) / 2; 627 | + screen_dest_rect.h = src_rect.h; 628 | + } 629 | + // SLK end 630 | SubBlit(msurface, src_rect, screen_dest_rect, InterlaceField); 631 | } 632 | else 633 | @@ -1687,25 +1952,61 @@ 634 | } 635 | else 636 | { 637 | - sub_dest_rect.x = screen_dest_rect.x; 638 | - sub_dest_rect.w = screen_dest_rect.w; 639 | - sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 640 | - sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 641 | - } 642 | + if (use_native_resolution || use_super_resolution) 643 | + { 644 | + // SLK - (prevent) resizing and centering 645 | + //printf(" src_rect: %dx%d %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 646 | + sub_dest_rect.x = screen_dest_rect.x; 647 | + sub_dest_rect.w = screen_dest_rect.w; 648 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y); // * screen_dest_rect.h / src_rect.h; 649 | + //printf(" sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 650 | + //printf(" sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 651 | + //printf(" sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 652 | + 653 | + if (sub_src_rect.w >= resolution_to_change_w) // horizontal crop to fit screen 654 | + { 655 | + sub_src_rect.x = sub_src_rect.x + ((sub_src_rect.w - resolution_to_change_w) / 2); 656 | + sub_src_rect.w = resolution_to_change_w; 657 | + } 658 | + 659 | + if (native_resolution_vcenter == true) // default vertical centering 660 | + { 661 | + sub_dest_rect.y = sub_dest_rect.y + (resolution_to_change_h - sub_src_rect.h) / 2; 662 | + sub_dest_rect.h = sub_src_rect.h; 663 | + } 664 | + else // fill screen (psx - half black screen fix) 665 | + { 666 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 667 | + } 668 | + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 669 | + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 670 | + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 671 | + } 672 | + else 673 | + { 674 | + sub_dest_rect.x = screen_dest_rect.x; 675 | + sub_dest_rect.w = screen_dest_rect.w; 676 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 677 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 678 | + } 679 | 680 | - if(!sub_dest_rect.h) // May occur with small yscale values in certain cases, so prevent triggering an assert() 681 | - sub_dest_rect.h = 1; 682 | + if (!sub_dest_rect.h) 683 | + { 684 | + sub_dest_rect.h = 1; 685 | + } // May occur with small yscale values in certain cases, so prevent triggering an assert() 686 | + // SLK - end 687 | 688 | - // Blit here! 689 | - SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 690 | + 691 | + // Blit here! 692 | + SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 693 | 694 | - last_y = y; 695 | + last_y = y; 696 | 697 | - if(y != (src_rect.y + src_rect.h)) 698 | - { 699 | - last_width = LineWidths[y]; 700 | + if (y != (src_rect.y + src_rect.h)) 701 | + { 702 | + last_width = LineWidths[y]; 703 | + } 704 | } 705 | - 706 | } 707 | } 708 | } 709 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video.h ./emu4crt/src/drivers/video.h 710 | --- ./mednafen/src/drivers/video.h 2019-12-24 04:24:48.000000000 -0800 711 | +++ ./emu4crt/src/drivers/video.h 2020-01-14 14:02:58.847856679 -0800 712 | @@ -36,6 +36,13 @@ 713 | 714 | void Video_Sync(MDFNGI* gi); 715 | 716 | +// SLK 717 | +void Video_ChangeResolution(MDFNGI* gi, int w, int h); 718 | +#ifdef WIN32 719 | +void Video_WinSetVideoMode(int iWidth, int iHeight); 720 | +#endif 721 | +// SLK 722 | + 723 | void Video_Exposed(void); 724 | 725 | void Video_Kill(void) MDFN_COLD; 726 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video-state.cpp ./emu4crt/src/drivers/video-state.cpp 727 | --- ./mednafen/src/drivers/video-state.cpp 2019-12-24 04:24:48.000000000 -0800 728 | +++ ./emu4crt/src/drivers/video-state.cpp 2019-12-26 07:31:19.375343000 -0800 729 | @@ -161,7 +161,7 @@ 730 | } // end if(StateStatus) 731 | 732 | if(PreviewSurface) 733 | - { 734 | +{ 735 | MDFN_Rect tdrect, drect; 736 | 737 | int meow = ((screen_w / CurGame->nominal_width) + 1) / 2; 738 | @@ -169,19 +169,51 @@ 739 | 740 | tdrect.w = TextRect.w * meow; 741 | tdrect.h = TextRect.h * meow; 742 | - tdrect.x = (screen_w - tdrect.w) / 2; 743 | - tdrect.y = screen_h - tdrect.h; 744 | - 745 | - BlitRaw(TextSurface, &TextRect, &tdrect); 746 | - 747 | - drect.w = PreviewRect.w * meow; 748 | - drect.h = PreviewRect.h * meow; 749 | - drect.x = (screen_w - drect.w) / 2; 750 | - drect.y = screen_h - drect.h - tdrect.h - 4; 751 | - 752 | - BlitRaw(PreviewSurface, &PreviewRect, &drect); 753 | - 754 | - } 755 | + tdrect.x = (screen_w - tdrect.w) / 2; 756 | + // SLK - Custom savestate selection OSD 757 | + if(use_native_resolution || use_super_resolution) 758 | + { 759 | + switch(screen_h){ 760 | + case 240:tdrect.y = screen_h - tdrect.h - 18; 761 | + break; 762 | + case 288:tdrect.y = screen_h - tdrect.h - 32; 763 | + break; 764 | + case 480:tdrect.y = screen_h - tdrect.h - 32; 765 | + break; 766 | + case 576:tdrect.y = screen_h - tdrect.h - 64; 767 | + break; 768 | + default:tdrect.y = screen_h - tdrect.h; 769 | + } 770 | + if(use_super_resolution) 771 | + { 772 | + tdrect.w = tdrect.w * 8; 773 | + tdrect.x = (screen_w - tdrect.w) / 2; 774 | + } 775 | + 776 | + BlitRaw(TextSurface, &TextRect, &tdrect); 777 | + 778 | + drect.w = screen_w * 0.5 + 3; // TODO: Why 3 ??? 779 | + drect.h = screen_h * 0.5 + 3; 780 | + drect.x = (screen_w - drect.w) / 2; 781 | + drect.y = tdrect.y - drect.h; // SLK 782 | + 783 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 784 | + } 785 | + else // native OSD display 786 | + { 787 | + tdrect.y = screen_h - tdrect.h; 788 | + 789 | + BlitRaw(TextSurface, &TextRect, &tdrect); 790 | + 791 | + drect.w = PreviewRect.w * meow; 792 | + drect.h = PreviewRect.h * meow; 793 | + drect.x = (screen_w - drect.w) / 2; 794 | + drect.y = screen_h - drect.h - tdrect.h - 4; 795 | + 796 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 797 | + } 798 | + // SLK - end 799 | + } 800 | 801 | } 802 | 803 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.cpp ./emu4crt/src/mednafen.cpp 804 | --- ./mednafen/src/mednafen.cpp 2019-12-24 04:24:48.000000000 -0800 805 | +++ ./emu4crt/src/mednafen.cpp 2020-01-11 19:02:13.691141241 -0800 806 | @@ -51,6 +51,18 @@ 807 | #include "video/tblur.h" 808 | #include "qtrecord.h" 809 | 810 | +// SLK 811 | +bool use_native_resolution = false; 812 | +bool use_super_resolution = false; 813 | +bool resolution_to_change; 814 | +int resolution_to_change_w; 815 | +int resolution_to_change_h; 816 | +int current_resolution_w; 817 | +int current_resolution_h; 818 | +bool native_resolution_vcenter = true; 819 | +// SLK end 820 | + 821 | + 822 | namespace Mednafen 823 | { 824 | 825 | @@ -1261,7 +1273,7 @@ 826 | throw MDFN_Error(0, _("Unrecognized file format.")); 827 | } 828 | 829 | - MDFN_printf(_("Using module: %s(%s)\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); 830 | + MDFN_printf(_("Using module:%s (%s)\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); 831 | { 832 | MDFN_AutoIndent aindentgm(1); 833 | 834 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.h ./emu4crt/src/mednafen.h 835 | --- ./mednafen/src/mednafen.h 2019-12-24 04:24:48.000000000 -0800 836 | +++ ./emu4crt/src/mednafen.h 2020-01-12 13:00:27.436983766 -0800 837 | @@ -21,6 +21,18 @@ 838 | #include "settings.h" 839 | #include "NativeVFS.h" 840 | 841 | +// SLK 842 | +extern bool use_native_resolution; 843 | +extern bool use_super_resolution; 844 | +extern bool native_resolution_vcenter; 845 | +extern bool resolution_to_change; 846 | +extern int resolution_to_change_w; 847 | +extern int resolution_to_change_h; 848 | +extern int current_resolution_w; 849 | +extern int current_resolution_h; 850 | +// SLK end 851 | + 852 | + 853 | namespace Mednafen 854 | { 855 | MDFN_HIDE extern NativeVFS NVFS; 856 | diff -Naur -r --no-dereference ./mednafen/src/nes/nes.cpp ./emu4crt/src/nes/nes.cpp 857 | --- ./mednafen/src/nes/nes.cpp 2019-12-24 04:24:48.000000000 -0800 858 | +++ ./emu4crt/src/nes/nes.cpp 2019-12-26 07:31:19.375343000 -0800 859 | @@ -287,7 +287,21 @@ 860 | MDFNGameInfo->fps = PAL? 838977920 : 1008307711; 861 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); 862 | } 863 | - 864 | + 865 | + //SLK 866 | + if(PAL) 867 | + { 868 | + resolution_to_change_h = 288; 869 | + } 870 | + else 871 | + { 872 | + resolution_to_change_h = 240; 873 | + } 874 | + resolution_to_change_w = 256; 875 | + resolution_to_change = true; 876 | + //SLK end 877 | + 878 | + 879 | X6502_Init(); 880 | MDFNPPU_Init(); 881 | MDFNSND_Init(PAL); 882 | diff -Naur -r --no-dereference ./mednafen/src/pce/pce.cpp ./emu4crt/src/pce/pce.cpp 883 | --- ./mednafen/src/pce/pce.cpp 2019-12-24 04:24:48.000000000 -0800 884 | +++ ./emu4crt/src/pce/pce.cpp 2019-12-26 07:31:19.379343000 -0800 885 | @@ -414,6 +414,16 @@ 886 | for(unsigned ch = 0; ch < 2; ch++) 887 | HRBufs[ch] = new OwlBuffer(); 888 | 889 | + // SLK 890 | + if(MDFN_GetSettingB("pce.arcadecard")) 891 | + { 892 | + resolution_to_change_w = 256; 893 | + resolution_to_change_h = 240; 894 | + resolution_to_change = true; 895 | + } 896 | + // SLK 897 | + 898 | + 899 | // FIXME: Make these globals less global! 900 | PCE_ACEnabled = MDFN_GetSettingB("pce.arcadecard"); 901 | 902 | diff -Naur -r --no-dereference ./mednafen/src/pce/vce.cpp ./emu4crt/src/pce/vce.cpp 903 | --- ./mednafen/src/pce/vce.cpp 2019-12-24 04:24:48.000000000 -0800 904 | +++ ./emu4crt/src/pce/vce.cpp 2019-12-26 07:31:19.379343000 -0800 905 | @@ -35,6 +35,11 @@ 906 | namespace MDFN_IEN_PCE 907 | { 908 | 909 | +// SLK 910 | +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start 911 | +static const int width_list[4] = {256, 320, 512, 512 }; // SLK 912 | +// SLK end 913 | + 914 | static const int vce_ratios[4] = { 4, 3, 2, 2 }; 915 | 916 | static MDFN_FASTCALL NO_INLINE int32 Sync(const int32 timestamp); 917 | @@ -634,6 +639,18 @@ 918 | dot_clock_ratio = vce_ratios[dot_clock]; 919 | 920 | CR = V; 921 | + 922 | + // SLK 923 | + if(dot_clock != prev_dot_clock) 924 | + { 925 | + printf("PCE - VCE - dot_clock change to: %d\n",dot_clock); 926 | + prev_dot_clock = dot_clock; 927 | + resolution_to_change_w = width_list[dot_clock]; 928 | + resolution_to_change_h = 240; 929 | + resolution_to_change = true; 930 | + } 931 | + // SLK end 932 | + 933 | } 934 | 935 | void VCE::SetPixelFormat(const MDFN_PixelFormat &format, const uint8* CustomColorMap, const uint32 CustomColorMapLen) 936 | diff -Naur -r --no-dereference ./mednafen/src/psx/gpu.cpp ./emu4crt/src/psx/gpu.cpp 937 | --- ./mednafen/src/psx/gpu.cpp 2019-12-24 04:24:48.000000000 -0800 938 | +++ ./emu4crt/src/psx/gpu.cpp 2020-01-11 19:26:12.184709007 -0800 939 | @@ -24,6 +24,7 @@ 940 | #include "psx.h" 941 | #include "timer.h" 942 | 943 | +#include // SLK 944 | /* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ 945 | 946 | /* 947 | @@ -74,6 +75,79 @@ 948 | } 949 | using namespace PS_GPU_INTERNAL; 950 | 951 | +// SLK 952 | +uint32 PreviousDisplayMode; 953 | +int prev_resolution_w; 954 | +int prev_resolution_h; 955 | +int res_change_count; 956 | + 957 | + 958 | +void GPU_NewDisplayMode(int V) // SLK - identify GPU new resolution, set global variables used in MAIN & VIDEO 959 | +{ 960 | + // GP1(08h) - Display mode 961 | + // 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 962 | + // 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 963 | + // 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 964 | + // 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 965 | + // 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 966 | + // 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 967 | + // 7 "Reverseflag" (0=Normal, 1=Distorted) ;GPUSTAT.14 968 | + // source: http://problemkaputt.de/psx-spx.txt 969 | + 970 | + // Width 971 | + if((V & 0x40) == 0x40) 972 | + { 973 | + resolution_to_change_w = 368; 974 | + } 975 | + else 976 | + { 977 | + switch(V & 0x3) 978 | + { 979 | + case 0x00: 980 | + resolution_to_change_w = 256; 981 | + break; 982 | + case 0x01: 983 | + resolution_to_change_w = 320; 984 | + break; 985 | + case 0x02: 986 | + resolution_to_change_w = 512; 987 | + break; 988 | + case 0x03: 989 | + resolution_to_change_w = 640; 990 | + break; 991 | + } 992 | + } 993 | + // Height 994 | + if ((V & 8) == 8) 995 | + { //PAL 996 | + if ((V & 32) == 32) {resolution_to_change_h = 576;} //5 997 | + else {resolution_to_change_h = 288;} 998 | + } 999 | + else 1000 | + { // NTSC 1001 | + if ((V & 32) == 32){resolution_to_change_h = 480;} //5 1002 | + else {resolution_to_change_h = 240;} 1003 | + } 1004 | + 1005 | + if(prev_resolution_w != resolution_to_change_w || prev_resolution_h != resolution_to_change_h) 1006 | + { 1007 | + if(res_change_count < 2) 1008 | + { 1009 | + res_change_count += 1; 1010 | + printf("PSX GPU - Startup resolution change bypass (%d).\n",res_change_count); 1011 | + native_resolution_vcenter = false; // No need Vertical centering for PSX module. 1012 | + } 1013 | + else{ 1014 | + prev_resolution_w = resolution_to_change_w; // will be used in VIDEO.cpp 1015 | + prev_resolution_h = resolution_to_change_h; 1016 | + printf("PSX - GPU register - resolution change to: %dx%d (V=%d)\n",resolution_to_change_w,resolution_to_change_h,V); 1017 | + resolution_to_change = true; // will be reset in VIDEO.cpp 1018 | + 1019 | + } 1020 | + } 1021 | +} 1022 | +// SLK end 1023 | + 1024 | void GPU_Init(bool pal_clock_and_tv) 1025 | { 1026 | static const int8 dither_table[4][4] = 1027 | @@ -110,11 +184,25 @@ 1028 | { 1029 | GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) 1030 | hmc_to_visible = 520; 1031 | + 1032 | + //SLK 1033 | + resolution_to_change = true; 1034 | + resolution_to_change_w = 640; 1035 | + resolution_to_change_h = 480; 1036 | + printf("PSX - GPU Init - NTSC mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1037 | + 1038 | } 1039 | else // PAL clock 1040 | { 1041 | GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) 1042 | hmc_to_visible = 560; 1043 | + 1044 | + //SLK 1045 | + resolution_to_change = true; 1046 | + resolution_to_change_w = 640; 1047 | + resolution_to_change_h = 576; 1048 | + printf("PSX - GPU Init - PAL mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1049 | + 1050 | } 1051 | 1052 | memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); 1053 | @@ -905,6 +993,11 @@ 1054 | case 0x08: 1055 | //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); 1056 | DisplayMode = V & 0xFF; 1057 | + if(PreviousDisplayMode != DisplayMode) // SLK - Trap GPU resolution change 1058 | + { 1059 | + PreviousDisplayMode = DisplayMode; 1060 | + GPU_NewDisplayMode(V); 1061 | + } 1062 | break; 1063 | 1064 | case 0x09: 1065 | @@ -1118,8 +1211,13 @@ 1066 | MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp) 1067 | { 1068 | const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); 1069 | - const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) 1070 | - const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo 1071 | + 1072 | + // SLK - Hotdog mod 1/2 - Fix Horizontal centering & cropping 1073 | + //const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) 1074 | + //const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo 1075 | + const uint32 dmw = 2560 / DotClockRatios[dmc]; // Must be <= (768 - 32) 1076 | + const uint32 dmpa = 0; 1077 | +// SLK - Hotdog mod 1/2 - end 1078 | 1079 | int32 sys_clocks = sys_timestamp - lastts; 1080 | int32 gpu_clocks; 1081 | @@ -1273,7 +1371,7 @@ 1082 | char buffer[256]; 1083 | trio_snprintf(buffer, sizeof(buffer), _("VIDEO STANDARD MISMATCH")); 1084 | DrawText(surface, 0, (DisplayRect->h / 2) - (13 / 2), buffer, 1085 | - surface->MakeColor(0x00, 0xFF, 0x00), MDFN_FONT_6x13_12x13, DisplayRect->w); 1086 | + surface->MakeColor(0x00, 0xFF, 0x00), MDFN_FONT_6x13_12x13, DisplayRect->w); 1087 | } 1088 | } 1089 | else 1090 | @@ -1293,8 +1391,8 @@ 1091 | 1092 | for(int i = 0; i < (DisplayRect->y + DisplayRect->h); i++) 1093 | { 1094 | - surface->pixels[i * surface->pitch32 + drxbo + 0] = 1095 | - surface->pixels[i * surface->pitch32 + drxbo + 1] = black; 1096 | + surface->pixels[i * surface->pitch32 + drxbo + 0] = 1097 | + surface->pixels[i * surface->pitch32 + drxbo + 1] = black; 1098 | LineWidths[i] = 2; 1099 | } 1100 | } 1101 | @@ -1370,16 +1468,35 @@ 1102 | dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 1103 | dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 1104 | 1105 | + 1106 | + // SLK - Hotdog mod 2/2 - Fix horizontal centering & cropping 1107 | + int32 actualGameBufferWidth = (HorizEnd - HorizStart) / DotClockRatios[dmc]; 1108 | + int32 ourBufferWidth = dmw; 1109 | + 1110 | + int32 leftOffset = (actualGameBufferWidth - ourBufferWidth) / 2; 1111 | + //leftOffset *= DotClockRatios[dmc]; // Get back into PSX GPU co-ords. 1112 | + leftOffset = std::max(leftOffset, 0); // Make sure not negative 1113 | + dx_start += leftOffset; // Offset the PSX buffer to render relative to our frame. 1114 | + // 1115 | + 1116 | + dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 1117 | + dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 1118 | + 1119 | if(dx_end < dx_start) 1120 | dx_end = dx_start; 1121 | 1122 | dx_start = dx_start / DotClockRatios[dmc]; 1123 | dx_end = dx_end / DotClockRatios[dmc]; 1124 | 1125 | - dx_start -= hmc_to_visible / DotClockRatios[dmc]; 1126 | - dx_end -= hmc_to_visible / DotClockRatios[dmc]; 1127 | - dx_start += 7; 1128 | - dx_end += 7; 1129 | + dx_end -= dx_start; 1130 | + dx_start = -leftOffset; 1131 | + 1132 | + // dx_start -= hmc_to_visible / DotClockRatios[dmc]; 1133 | + // dx_end -= hmc_to_visible / DotClockRatios[dmc]; 1134 | + // dx_start += 7; 1135 | + // dx_end += 7; 1136 | + 1137 | + // SLK - Hotdog mod 2/2 - end 1138 | 1139 | if(dx_start < 0) 1140 | { 1141 | @@ -1462,7 +1579,7 @@ 1142 | } // end while(gpu_clocks > 0) 1143 | 1144 | //puts("GPU Update End"); 1145 | - 1146 | + 1147 | TheEnd: 1148 | lastts = sys_timestamp; 1149 | 1150 | diff -Naur -r --no-dereference ./mednafen/src/psx/psx.cpp ./emu4crt/src/psx/psx.cpp 1151 | --- ./mednafen/src/psx/psx.cpp 2019-12-24 04:24:48.000000000 -0800 1152 | +++ ./emu4crt/src/psx/psx.cpp 2020-01-09 15:39:25.370977307 -0800 1153 | @@ -1129,6 +1129,9 @@ 1154 | if(!espec->skip) 1155 | { 1156 | espec->LineWidths[0] = ~0; 1157 | + // SLK 1158 | + espec->DisplayRect.x = espec->DisplayRect.x + (espec->DisplayRect.w * 0.046875); 1159 | + // SLK 1160 | Player_Draw(espec->surface, &espec->DisplayRect, 0, espec->SoundBuf, espec->SoundBufSize); 1161 | } 1162 | } 1163 | diff -Naur -r --no-dereference ./mednafen/src/snes/interface.cpp ./emu4crt/src/snes/interface.cpp 1164 | --- ./mednafen/src/snes/interface.cpp 2019-12-24 04:24:48.000000000 -0800 1165 | +++ ./emu4crt/src/snes/interface.cpp 2020-01-01 05:54:16.407604000 -0800 1166 | @@ -73,6 +73,11 @@ 1167 | 1168 | static std::vector ColorMap; // [32768] 1169 | 1170 | +// SLK 1171 | +int prev_resolution_w; 1172 | +int prev_resolution_h; 1173 | +// SLK - end 1174 | + 1175 | static void BuildColorMap(MDFN_PixelFormat &format, uint8* CustomColorMap) 1176 | { 1177 | for(int x = 0; x < 32768; x++) 1178 | @@ -545,6 +550,23 @@ 1179 | MDFNGameInfo->fps = PAL ? 838977920 : 1008307711; 1180 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(32040.5); 1181 | 1182 | + // SLK - init. dynamic display video resolution - progressive by default 1183 | + printf("SNES Interface - Regional mode: %s \n",(PAL ? "PAL" : "NTSC")); 1184 | + if(PAL) 1185 | + { 1186 | + resolution_to_change_h = 288; 1187 | + } 1188 | + else 1189 | + { 1190 | + printf(" Video mode set to 256 x 240\n"); 1191 | + resolution_to_change_h = 240; 1192 | + } 1193 | + resolution_to_change_w = 256; 1194 | + resolution_to_change = true; 1195 | + prev_resolution_w = resolution_to_change_w; 1196 | + prev_resolution_h = resolution_to_change_h; 1197 | + // SLK - end 1198 | + 1199 | if(!snsf_loader) 1200 | { 1201 | EnableHBlend = MDFN_GetSettingB("snes.h_blend"); 1202 | @@ -889,6 +911,32 @@ 1203 | bSNES_v059::system.run_mednafen_custom(); 1204 | bSNES_v059::ppu.enable_renderer(true); 1205 | 1206 | + // SLK - guess SNES active resolution 1207 | + //printf("SNES Interface - Emulate - %dx%d - %d,%d\n",tdr->w,tdr->h,tdr->x,tdr->y); 1208 | + if(tdr->h > 10 && tdr->w > 10 && tdr->w != prev_resolution_w) 1209 | + { 1210 | + resolution_to_change = true; 1211 | + resolution_to_change_w = tdr->w; 1212 | + } 1213 | + if(tdr->h > 10 && tdr->w > 10 && tdr->h != prev_resolution_h) 1214 | + { 1215 | + resolution_to_change = true; 1216 | + if(tdr->h <= 400) 1217 | + { 1218 | + resolution_to_change_h = bSNES_v059::system.region() ? 288 : 240; 1219 | + } 1220 | + else 1221 | + { 1222 | + resolution_to_change_h = bSNES_v059::system.region() ? 576 : 480; 1223 | + } 1224 | + } 1225 | + if(resolution_to_change) 1226 | + { 1227 | + //printf("SNES - Interface - Resolution change detected: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1228 | + prev_resolution_w = resolution_to_change_w; 1229 | + prev_resolution_h = tdr->h; 1230 | + } 1231 | + // SLK - end 1232 | 1233 | // 1234 | // Blank out any missed lines(for e.g. display height change with PAL emulation) 1235 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_common.h ./emu4crt/src/snes_faust/ppu_common.h 1236 | --- ./mednafen/src/snes_faust/ppu_common.h 2019-12-24 04:24:48.000000000 -0800 1237 | +++ ./emu4crt/src/snes_faust/ppu_common.h 2020-01-12 12:59:54.692893384 -0800 1238 | @@ -21,5 +21,4 @@ 1239 | void PPU_PokeCGRAM(uint32 addr, uint16 val) MDFN_COLD; 1240 | void PPU_PokeOAM(uint32 addr, uint8 val) MDFN_COLD; 1241 | void PPU_PokeOAMHI(uint32 addr, uint8 val) MDFN_COLD; 1242 | -void PPU_SetRegister(const unsigned id, const uint32 value) MDFN_COLD; 1243 | - 1244 | +void PPU_SetRegister(const unsigned id, const uint32 value) MDFN_COLD; 1245 | \ No newline at end of file 1246 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mt.cpp ./emu4crt/src/snes_faust/ppu_mt.cpp 1247 | --- ./mednafen/src/snes_faust/ppu_mt.cpp 2019-12-24 04:24:48.000000000 -0800 1248 | +++ ./emu4crt/src/snes_faust/ppu_mt.cpp 2020-01-01 14:56:52.304295000 -0800 1249 | @@ -43,6 +43,12 @@ 1250 | namespace PPU_MT 1251 | { 1252 | 1253 | +// SLK 1254 | +int prev_resolution_w; 1255 | +int prev_resolution_h; 1256 | +// SLK 1257 | + 1258 | + 1259 | static struct 1260 | { 1261 | uint32 lastts; 1262 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mtrender.cpp ./emu4crt/src/snes_faust/ppu_mtrender.cpp 1263 | --- ./mednafen/src/snes_faust/ppu_mtrender.cpp 2019-12-24 04:24:48.000000000 -0800 1264 | +++ ./emu4crt/src/snes_faust/ppu_mtrender.cpp 2020-01-01 14:57:23.375643000 -0800 1265 | @@ -23,6 +23,10 @@ 1266 | #include "ppu.h" 1267 | #include "ppu_mtrender.h" 1268 | 1269 | +// SLK 1270 | +// #include 1271 | +// SLK end 1272 | + 1273 | #include 1274 | #include 1275 | 1276 | @@ -45,6 +49,12 @@ 1277 | namespace PPU_MTRENDER 1278 | { 1279 | 1280 | +// SLK 1281 | +int prev_resolution_w; 1282 | +int prev_resolution_h; 1283 | +// SLK 1284 | + 1285 | + 1286 | PPU_S PPU; 1287 | 1288 | #include "ppu_render_common.inc" 1289 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_render_common.inc ./emu4crt/src/snes_faust/ppu_render_common.inc 1290 | --- ./mednafen/src/snes_faust/ppu_render_common.inc 2019-12-24 04:24:48.000000000 -0800 1291 | +++ ./emu4crt/src/snes_faust/ppu_render_common.inc 2020-01-01 14:48:50.555151000 -0800 1292 | @@ -1621,6 +1621,16 @@ 1293 | T* const out_target = es->surface->pix() + out_line * es->surface->pitchinpix; 1294 | const uint32 w = ((BGMode & 0x7) == 0x5 || (BGMode & 0x7) == 0x6 || (ScreenMode & 0x08)) ? 512 : 256; 1295 | 1296 | +// SLK 1297 | + if(w != prev_resolution_w) 1298 | + { 1299 | + resolution_to_change_w = w; 1300 | + prev_resolution_w = w; 1301 | + resolution_to_change = true; 1302 | + } 1303 | +// SLK - end 1304 | + 1305 | + 1306 | es->LineWidths[out_line] = w; 1307 | // 1308 | LineTarget++; 1309 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_st.cpp ./emu4crt/src/snes_faust/ppu_st.cpp 1310 | --- ./mednafen/src/snes_faust/ppu_st.cpp 2019-12-24 04:24:48.000000000 -0800 1311 | +++ ./emu4crt/src/snes_faust/ppu_st.cpp 2020-01-01 14:56:43.112533000 -0800 1312 | @@ -34,6 +34,10 @@ 1313 | #include "input.h" 1314 | #include "cart.h" 1315 | 1316 | +// SLK 1317 | +#include 1318 | +// SLK end 1319 | + 1320 | #include 1321 | #include 1322 | 1323 | @@ -56,6 +60,11 @@ 1324 | namespace PPU_ST 1325 | { 1326 | 1327 | +// SLK 1328 | +int prev_resolution_w; 1329 | +int prev_resolution_h; 1330 | +// SLK 1331 | + 1332 | struct PPU_S 1333 | { 1334 | uint32 lastts; 1335 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/snes.cpp ./emu4crt/src/snes_faust/snes.cpp 1336 | --- ./mednafen/src/snes_faust/snes.cpp 2019-12-24 04:24:48.000000000 -0800 1337 | +++ ./emu4crt/src/snes_faust/snes.cpp 2020-01-01 14:50:31.525517000 -0800 1338 | @@ -43,6 +43,7 @@ 1339 | static MemoryStream* SpecExSS = NULL; 1340 | static int32 SpecExAudioExpected; 1341 | 1342 | + 1343 | struct ReadPatchInfoStruct 1344 | { 1345 | bool operator<(const ReadPatchInfoStruct& o) const 1346 | @@ -604,6 +605,8 @@ 1347 | } 1348 | } 1349 | 1350 | + 1351 | + 1352 | DMA_Init(); 1353 | // 1354 | // 1355 | @@ -617,6 +620,9 @@ 1356 | const unsigned region = MDFN_GetSettingUI("snes_faust.region"); 1357 | bool IsPAL, IsPALPPUBit; 1358 | 1359 | + 1360 | + 1361 | + 1362 | if(snsf_loader) 1363 | { 1364 | uint8* const cart_ram = CART_GetRAMPointer(); 1365 | @@ -671,6 +677,23 @@ 1366 | } 1367 | // 1368 | // 1369 | + 1370 | +// SLK - init. dynamic display video resolution - progressive by default 1371 | + printf("SNES FAUST snes - Regional mode: %s \n",(IsPAL ? "PAL" : "NTSC")); 1372 | + if(IsPAL) 1373 | + { 1374 | + resolution_to_change_h = 288; 1375 | + } 1376 | + else 1377 | + { 1378 | + printf(" Video mode set to 256 x 240\n"); 1379 | + resolution_to_change_h = 240; 1380 | + } 1381 | + resolution_to_change_w = 256; 1382 | + resolution_to_change = true; 1383 | + // SLK - end 1384 | + 1385 | + 1386 | INPUT_Init(); 1387 | { 1388 | const bool mte[2] = { MDFN_GetSettingB("snes_faust.input.sport1.multitap"), MDFN_GetSettingB("snes_faust.input.sport2.multitap") }; 1389 | diff -Naur -r --no-dereference ./mednafen/src/ss/vdp2_render.cpp ./emu4crt/src/ss/vdp2_render.cpp 1390 | --- ./mednafen/src/ss/vdp2_render.cpp 2019-12-24 04:24:48.000000000 -0800 1391 | +++ ./emu4crt/src/ss/vdp2_render.cpp 2019-12-26 07:31:34.355158000 -0800 1392 | @@ -145,6 +145,14 @@ 1393 | static uint8 LineColorCCRatio; 1394 | static uint8 BackCCRatio; 1395 | 1396 | +//SLK 1397 | +static uint8 prev_InterlaceMode = 0; 1398 | +static uint8 prev_HRes = 0; 1399 | +static uint8 prev_VRes = 0; 1400 | +static bool prev_BorderMode = 0; 1401 | +// SLK end 1402 | + 1403 | + 1404 | // 1405 | static struct 1406 | { 1407 | @@ -550,6 +558,39 @@ 1408 | InterlaceMode = (V >> 6) & 0x3; 1409 | VRes = (V >> 4) & 0x3; 1410 | HRes = (V >> 0) & 0x7; 1411 | + // SLK 1412 | + if(InterlaceMode != prev_InterlaceMode || HRes != prev_HRes) 1413 | + { 1414 | + printf("VDP2 Render - Television mode changed: %d\n",V); 1415 | + printf(" BorderMode: %d\n",BorderMode); 1416 | + printf(" PAL: %d\n",PAL); 1417 | + printf(" InterlaceMode: %d\n",InterlaceMode); 1418 | + printf(" VRes: %d\n",VRes); 1419 | + printf(" HRes: %d\n",HRes); 1420 | + prev_BorderMode = BorderMode; 1421 | + prev_InterlaceMode = InterlaceMode; 1422 | + prev_VRes = VRes; 1423 | + prev_HRes = HRes; 1424 | + // HRES 1425 | + switch(HRes){ 1426 | + case 0: 1427 | + resolution_to_change_w = 320; 1428 | + break; 1429 | + case 1: 1430 | + resolution_to_change_w = 352; 1431 | + break; 1432 | + case 2: 1433 | + resolution_to_change_w = 640; 1434 | + break; 1435 | + case 3: 1436 | + resolution_to_change_w = 704; 1437 | + break; 1438 | + } 1439 | + if(InterlaceMode >= 2){resolution_to_change_h = PAL ? 576 : 480;} else {resolution_to_change_h = PAL ? 288 : 240;} 1440 | + printf("SS - VDP2 Render - TV mode set to %dx%d",resolution_to_change_w,resolution_to_change_h); 1441 | + resolution_to_change = true; // Flag for video resolution change by VIDEO.cpp/MAIN.cpp 1442 | + } 1443 | + // SLK - end 1444 | break; 1445 | 1446 | case 0x02: 1447 | @@ -3295,12 +3336,20 @@ 1448 | { 1449 | gi->nominal_width = (ShowHOverscan ? 365 : 354); 1450 | gi->fb_height = 576; 1451 | + resolution_to_change_h = 288; // SLK - init crt mode 1452 | } 1453 | else 1454 | { 1455 | gi->nominal_width = (ShowHOverscan ? 302 : 292); 1456 | gi->fb_height = 480; 1457 | + resolution_to_change_h = 240; // SLK - init crt mode 1458 | } 1459 | + // SLK 1460 | + resolution_to_change_w = 320; 1461 | + resolution_to_change = true; // SLK - init crt mode 1462 | + // SLK - end 1463 | + 1464 | + 1465 | gi->nominal_height = LineVisLast + 1 - LineVisFirst; 1466 | 1467 | gi->lcm_width = (ShowHOverscan? 10560 : 10240); 1468 | diff -Naur -r --no-dereference ./mednafen/src/state.cpp ./emu4crt/src/state.cpp 1469 | --- ./mednafen/src/state.cpp 2019-12-24 04:24:48.000000000 -0800 1470 | +++ ./emu4crt/src/state.cpp 2019-12-26 07:31:35.795145000 -0800 1471 | @@ -470,6 +470,14 @@ 1472 | neowidth = MDFNGameInfo->nominal_width; 1473 | neoheight = MDFNGameInfo->nominal_height; 1474 | 1475 | + // SLK - Approximation to prevent SaveState snapshot corruption 1476 | + if(use_super_resolution) 1477 | + { 1478 | + neowidth = resolution_to_change_w; 1479 | + neoheight = DisplayRect->h; 1480 | + } 1481 | + // SLK - end 1482 | + 1483 | if(LineWidths[0] != ~0) 1484 | { 1485 | int32 first_w = LineWidths[DisplayRect->y]; 1486 | @@ -857,7 +865,9 @@ 1487 | MDFN_Error* me = dynamic_cast(&e); 1488 | 1489 | if(!fname && !suffix) 1490 | - MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1491 | + // SLK 1492 | + // MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1493 | + MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d not found."), CurrentState); // SLK - shorten message to fit low-res rendering 1494 | else 1495 | { 1496 | // FIXME: Autosave kludgery, refactor interfaces in the future to make cleaner. 1497 | -------------------------------------------------------------------------------- /patches/mednafen-1.24.1-emu4crt-A11.patch: -------------------------------------------------------------------------------- 1 | diff -Naur -r --no-dereference ./mednafen/configure ./emu4crt/configure 2 | --- ./mednafen/configure 2019-12-24 04:24:48.000000000 -0800 3 | +++ ./emu4crt/configure 2019-12-26 07:29:42.895790000 -0800 4 | @@ -18085,7 +18085,8 @@ 5 | fi 6 | 7 | 8 | - LIBS="-mconsole -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 9 | +/* SLK - switch -mconsole */ 10 | + LIBS="-mwindows -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" 11 | CPPFLAGS="-D_LFS64_LARGEFILE=1 $CPPFLAGS" 12 | elif expr x"$host" : 'x.*djgpp' > /dev/null; then 13 | 14 | diff -Naur -r --no-dereference ./mednafen/Documentation/modules.def ./emu4crt/Documentation/modules.def 15 | --- ./mednafen/Documentation/modules.def 2019-12-24 04:24:48.000000000 -0800 16 | +++ ./emu4crt/Documentation/modules.def 2020-03-24 13:59:37.091288814 -0700 17 | @@ -1,4 +1,4 @@ 18 | -1.24.1 19 | +1.24.1-UNSTABLE-emu4crt-A11 20 | apple2 21 | Apple II/II+ 22 | 250 23 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.cpp ./emu4crt/src/drivers/main.cpp 24 | --- ./mednafen/src/drivers/main.cpp 2019-12-24 04:24:48.000000000 -0800 25 | +++ ./emu4crt/src/drivers/main.cpp 2020-01-14 14:27:35.903453000 -0800 26 | @@ -273,6 +273,7 @@ 27 | MDFNGI *CurGame=NULL; 28 | 29 | 30 | + 31 | #ifdef WIN32 32 | static std::string GetModuleFileName_UTF8(HMODULE hModule) 33 | { 34 | @@ -287,6 +288,47 @@ 35 | return UTF16_to_UTF8(&path[0], nullptr, true); 36 | } 37 | 38 | + 39 | +static bool HandleConsoleMadness(void) // SLK - enforce stdout.txt & stderr.txt out to files 40 | +{ 41 | + bool ret; 42 | + if(AllocConsole()) 43 | + { 44 | + HWND cwin = GetConsoleWindow(); 45 | + ShowWindow(cwin, SW_HIDE); 46 | + 47 | + freopen("CONOUT$", "w", stdout); 48 | + freopen("CONOUT$", "w", stderr); 49 | + 50 | + SetConsoleOutputCP(65001); // UTF-8 51 | + 52 | + std::string path; 53 | + size_t catpos; // Meow meow. 54 | + path = GetModuleFileName_UTF8(NULL); 55 | + if((catpos = path.find_last_of('\\')) != std::string::npos) path.resize(catpos + 1); 56 | + const std::u16string stdout_path = UTF8_to_UTF16(path + "stdout.txt", nullptr, true); 57 | + const std::u16string stderr_path = UTF8_to_UTF16(path + "stderr.txt", nullptr, true); 58 | + int new_stdout = -1; 59 | + int new_stderr = -1; 60 | + new_stdout = _wopen((const wchar_t*)stdout_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 61 | + new_stderr = _wopen((const wchar_t*)stderr_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 62 | + 63 | + fflush(stdout); 64 | + fflush(stderr); 65 | + 66 | + dup2(new_stdout, fileno(stdout)); 67 | + dup2(new_stderr, fileno(stderr)); 68 | + 69 | + close(new_stdout); 70 | + close(new_stderr); 71 | + 72 | + } 73 | + ret = false; 74 | + return ret; 75 | +} 76 | + 77 | +/* // SLK - Disable native redirection functions due to switch back to windows application 78 | + 79 | // returns 1 if redirected, 0 if not redirected due to error, -1 if not redirected due to env variable 80 | static int RedirectSTDxxx(void) 81 | { 82 | @@ -398,6 +440,8 @@ 83 | 84 | return ret; 85 | } 86 | +*/ 87 | + 88 | #endif 89 | 90 | void Mednafen::MDFND_OutputNotice(MDFN_NoticeType t, const char* s) noexcept 91 | @@ -1034,6 +1078,10 @@ 92 | } 93 | 94 | static volatile unsigned NeedVideoSync = 0; 95 | +//SLK 96 | +static volatile unsigned NeedResolutionChange = 0; // trigger to switch window/fullscreen resolution 97 | +//SLK end 98 | + 99 | static int GameLoop(void *arg); 100 | int volatile GameThreadRun = 0; 101 | static bool MDFND_Update(int WhichVideoBuffer, int16 *Buffer, int Count); 102 | @@ -1267,56 +1315,84 @@ 103 | { 104 | while(GameThreadRun) 105 | { 106 | - int16 *sound; 107 | - int32 ssize; 108 | - bool fskip; 109 | - 110 | + //SLK - trap change resolution request 111 | + if(resolution_to_change) 112 | + { 113 | + if(use_native_resolution) 114 | + { 115 | + if((current_resolution_w != resolution_to_change_w) || (current_resolution_h != resolution_to_change_h)) 116 | + { 117 | + printf("MAIN - native resolution to switch!\n"); 118 | + NeedResolutionChange++; 119 | + } 120 | + else {printf("MAIN - resolution change bypassed\n");} 121 | + } 122 | + if(use_super_resolution) 123 | + { 124 | + if(resolution_to_change_h != current_resolution_h) 125 | + { 126 | + printf("MAIN - Super resolution to switch: 2560 x %d\n", resolution_to_change_h); 127 | + NeedResolutionChange++; 128 | + } 129 | + else {printf("MAIN - Super resolution change bypassed\n");} 130 | + } 131 | + resolution_to_change = false; 132 | + } 133 | + // SLK - end 134 | + 135 | + int16 *sound; 136 | + int32 ssize; 137 | + bool fskip; 138 | + 139 | /* If we requested a new video mode, wait until it's set before calling the emulation code again. 140 | */ 141 | - while(NeedVideoSync) 142 | - { 143 | - if(!GameThreadRun) return(1); // Might happen if video initialization failed 144 | - Time::SleepMS(2); 145 | - } 146 | 147 | - if(Sound_NeedReInit()) 148 | - GT_ReinitSound(); 149 | + //SLK 150 | + while(NeedVideoSync) 151 | + //while(NeedVideoSync || NeedResolutionChange) // need to wait during resolution change ??? 152 | + //SLK 153 | + { 154 | + if(!GameThreadRun) return(1); // Might happen if video initialization failed 155 | + Time::SleepMS(2); 156 | + } 157 | + if(Sound_NeedReInit()) 158 | + GT_ReinitSound(); 159 | 160 | - if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 161 | - ers.SetETtoRT(); 162 | - // 163 | - // 164 | - fskip = ers.NeedFrameSkip(); 165 | - fskip &= MDFN_GetSettingB("video.frameskip"); 166 | - fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 167 | - fskip |= (bool)NoWaiting; 168 | + if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. 169 | + ers.SetETtoRT(); 170 | + // 171 | + // 172 | + fskip = ers.NeedFrameSkip(); 173 | + fskip &= MDFN_GetSettingB("video.frameskip"); 174 | + fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); 175 | + fskip |= (bool)NoWaiting; 176 | 177 | - //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 178 | + //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); 179 | 180 | - NeedFrameAdvance = false; 181 | - // 182 | - // 183 | - SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 184 | + NeedFrameAdvance = false; 185 | + // 186 | + // 187 | + SoftFB[SoftFB_BackBuffer].lw[0] = ~0; 188 | 189 | - // 190 | - // 191 | - // 192 | - EmulateSpecStruct espec; 193 | + // 194 | + // 195 | + // 196 | + EmulateSpecStruct espec; 197 | 198 | - espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 199 | - espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 200 | - espec.skip = fskip; 201 | - espec.soundmultiplier = CurGameSpeed; 202 | - espec.NeedRewind = DNeedRewind; 203 | - 204 | - espec.SoundRate = Sound_GetRate(); 205 | - espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 206 | - espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 207 | + espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); 208 | + espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); 209 | + espec.skip = fskip; 210 | + espec.soundmultiplier = CurGameSpeed; 211 | + espec.NeedRewind = DNeedRewind; 212 | 213 | - if(MDFN_UNLIKELY(StateRCTest)) 214 | - { 215 | - // Note: Won't work correctly with modules that do mid-sync. 216 | - EmulateSpecStruct estmp = espec; 217 | + espec.SoundRate = Sound_GetRate(); 218 | + espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); 219 | + espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; 220 | + 221 | + if(MDFN_UNLIKELY(StateRCTest)) 222 | + { 223 | + // Note: Won't work correctly with modules that do mid-sync. 224 | + EmulateSpecStruct estmp = espec; 225 | 226 | MemoryStream state0(524288); 227 | MemoryStream state1(524288); 228 | @@ -1334,19 +1410,19 @@ 229 | 230 | if(!(state1.map_size() == state2.map_size() && !memcmp(state1.map() + 32, state2.map() + 32, state1.map_size() - 32))) 231 | { 232 | - FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 233 | - FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 234 | + FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); 235 | + FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); 236 | 237 | - sd0.write(state1.map(), state1.map_size()); 238 | - sd1.write(state2.map(), state2.map_size()); 239 | - sd0.close(); 240 | - sd1.close(); 241 | - //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 242 | - abort(); 243 | + sd0.write(state1.map(), state1.map_size()); 244 | + sd1.write(state2.map(), state2.map_size()); 245 | + sd0.close(); 246 | + sd1.close(); 247 | + //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); 248 | + abort(); 249 | } 250 | - } 251 | - else 252 | - MDFNI_Emulate(&espec); 253 | + } 254 | + else 255 | + MDFNI_Emulate(&espec); 256 | 257 | if(MDFN_UNLIKELY(StateSLSTest)) 258 | { 259 | @@ -2149,7 +2225,7 @@ 260 | } 261 | 262 | #ifdef WIN32 263 | - HandleConsoleMadness(); 264 | + HandleConsoleMadness(); // SLK 265 | #endif 266 | 267 | //ThreadTest(); 268 | @@ -2424,12 +2500,20 @@ 269 | PumpWrap(); 270 | 271 | if(MDFN_UNLIKELY(NeedVideoSync)) 272 | - { 273 | - Video_Sync(CurGame); 274 | - PumpWrap(); 275 | - // 276 | - NeedVideoSync = 0; 277 | - } 278 | + { 279 | + Video_Sync(CurGame); 280 | + PumpWrap(); 281 | + NeedVideoSync = 0; 282 | + } 283 | + // SLK 284 | + if(MDFN_UNLIKELY(NeedResolutionChange)) 285 | + { 286 | + Video_ChangeResolution(CurGame, resolution_to_change_w, resolution_to_change_h); 287 | + // ??? PumpWrap(); 288 | + NeedResolutionChange = 0; 289 | + printf("MAIN - End of resolution change\n"); 290 | + } 291 | + // SLK END 292 | 293 | if(NeededWMInputBehavior_Dirty) 294 | { 295 | diff -Naur -r --no-dereference ./mednafen/src/drivers/main.h ./emu4crt/src/drivers/main.h 296 | --- ./mednafen/src/drivers/main.h 2019-12-24 04:24:48.000000000 -0800 297 | +++ ./emu4crt/src/drivers/main.h 2020-01-11 19:04:50.854434000 -0800 298 | @@ -70,7 +70,6 @@ 299 | bool GT_ReinitVideo(void); 300 | bool GT_ReinitSound(void); 301 | 302 | - 303 | void BuildSystemSetting(MDFNSetting *setting, const char *system_name, const char *name, const char *description, const char *description_extra, MDFNSettingType type, 304 | const char *default_value, const char *minimum = NULL, const char *maximum = NULL, 305 | bool (*validate_func)(const char *name, const char *value) = NULL, void (*ChangeNotification)(const char *name) = NULL, 306 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video.cpp ./emu4crt/src/drivers/video.cpp 307 | --- ./mednafen/src/drivers/video.cpp 2019-12-24 04:24:48.000000000 -0800 308 | +++ ./emu4crt/src/drivers/video.cpp 2020-03-24 13:52:56.578373345 -0700 309 | @@ -105,6 +105,16 @@ 310 | VDRIVER__COUNT 311 | }; 312 | 313 | +// SLK 314 | +static int _resolution_switch; 315 | +enum 316 | +{ 317 | + RES_STATIC = 0, 318 | + RES_NATIVE = 1, 319 | + RES_SUPER = 2 320 | +}; 321 | +// SLK - end 322 | + 323 | enum 324 | { 325 | NTVB_NONE = 0, 326 | @@ -146,6 +156,17 @@ 327 | { NULL, 0 }, 328 | }; 329 | 330 | +// SLK - custom setting 331 | +static const MDFNSetting_EnumList Resolution_Switch[] = 332 | +{ 333 | + // Legacy: 334 | + { "0", RES_STATIC}, 335 | + { "native", RES_NATIVE, "Native resolution", gettext_noop("Use emulated system native resolution.") }, 336 | + { "super", RES_SUPER, "Super resolution", gettext_noop("Use super resolutions") }, 337 | + { NULL, 0 }, 338 | +}; 339 | +// SLK - end 340 | + 341 | static const MDFNSetting GlobalVideoSettings[] = 342 | { 343 | { "video.driver", MDFNSF_NOFLAGS, gettext_noop("Video output driver."), NULL, MDFNST_ENUM, "default", NULL, NULL, NULL, NULL, VDriver_List }, 344 | @@ -161,6 +182,11 @@ 345 | MDFNST_BOOL, "1" }, 346 | 347 | { "video.disable_composition", MDFNSF_NOFLAGS, gettext_noop("Attempt to disable desktop composition."), gettext_noop("Currently, this setting only has an effect on Windows Vista and Windows 7(and probably the equivalent server versions as well)."), MDFNST_BOOL, "1" }, 348 | + 349 | + // SLK - admit new parameter 350 | + { "video.resolution_switch", MDFNSF_NOFLAGS, gettext_noop("Video resolution switch (0, native or super)."), NULL, MDFNST_ENUM, "0", NULL, NULL, NULL, NULL, Resolution_Switch}, 351 | + // SLK - end 352 | + 353 | }; 354 | 355 | static const MDFNSetting_EnumList StretchMode_List[] = 356 | @@ -746,6 +772,168 @@ 357 | SetMode(new_mode); 358 | #endif 359 | 360 | + 361 | +// SLK 362 | +void Video_ChangeResolution(MDFNGI *gi, int w, int h) 363 | +{ 364 | + printf("VIDEO - Video_ChangeResolution - Requested video mode: %d x %d\n", w, h); 365 | + 366 | + SMRect.w = (use_super_resolution) ? 2560 : w; 367 | + SMDRect.w = w; 368 | + 369 | + switch(h){ 370 | + case 240:SMDRect.y = h - SMDRect.h - 18; 371 | + break; 372 | + case 288:SMDRect.y = h - SMDRect.h - 32; 373 | + break; 374 | + case 480:SMDRect.y = h - SMDRect.h - 32; 375 | + break; 376 | + case 576:SMDRect.y = h - SMDRect.h - 64; 377 | + } 378 | + 379 | + if(SMSurface) 380 | + { 381 | + MDFN_PixelFormat SMFormat = SMSurface->format; 382 | + delete SMSurface; 383 | + SMSurface = nullptr; 384 | + SMSurface = new MDFN_Surface(NULL, SMRect.w, SMRect.h, SMRect.w, SMFormat); 385 | + } 386 | +/* TODO - rebuild HelpSurface on resolution change 387 | + if(HelpSurface) 388 | + { 389 | + delete HelpSurface; 390 | + HelpSurface = nullptr; 391 | + } 392 | +*/ 393 | + 394 | +// TODO: clean unwanted and duplicate code 395 | + if(video_settings.fullscreen == 0) 396 | + { 397 | + printf(" Video mode: WINDOWED\n"); 398 | + 399 | + SDL_SetWindowSize(window, w, h); 400 | + video_settings.xres = w; 401 | + video_settings.yres = h; 402 | + VideoGI->nominal_width = w; 403 | + screen_dest_rect.w = screen_w = w; 404 | + screen_dest_rect.h = screen_h = h; 405 | + screen_dest_rect.x = 0; 406 | + screen_dest_rect.y = 0; 407 | + int x, y; 408 | + SDL_GetWindowPosition(window, &x, &y); 409 | + SDL_PumpEvents(); 410 | + SDL_SetWindowPosition(window, x, y); 411 | + ogl_blitter->SetViewport(w, h); 412 | + current_resolution_h = h; 413 | + current_resolution_w = w; 414 | + } 415 | + else 416 | + { 417 | + printf(" Video mode: FULLSCREEN\n"); 418 | + 419 | + SDL_DisplayMode current; 420 | + SDL_DisplayMode mode; 421 | + SDL_DisplayMode trymode; 422 | + int displayIndex; 423 | + 424 | + displayIndex = SDL_GetWindowDisplayIndex(window); 425 | + if(displayIndex < 0) 426 | + { 427 | + printf(" ERROR Could not get screen index: %s\n", SDL_GetError()); 428 | + return; 429 | + } 430 | + else 431 | + { 432 | + printf(" Screen index: %d\n",displayIndex); 433 | + } 434 | + 435 | + if(SDL_GetCurrentDisplayMode(displayIndex, ¤t) != 0) 436 | + { 437 | + printf(" Could not get display mode for video display %d: %s\n", displayIndex, SDL_GetError()); 438 | + } 439 | + else 440 | + { 441 | + printf(" Display #%d: Current display mode is %dx%dpx @ %dhz.\n", displayIndex, current.w, current.h, current.refresh_rate); 442 | + trymode.w = w; 443 | + trymode.h = h; 444 | + trymode.refresh_rate = 0; 445 | + 446 | + if (SDL_GetClosestDisplayMode(displayIndex, &trymode, &mode) == NULL) 447 | + { 448 | + printf(" No suitable display mode was found, %s\n",SDL_GetError()); 449 | + } 450 | + else 451 | + { 452 | + printf(" Received: \t%dx%dpx @ %dhz \n", mode.w, mode.h, mode.refresh_rate); 453 | +#ifdef WIN32 454 | + // Use Win32 API for resolution chang 455 | + Video_WinSetVideoMode(mode.w,mode.h); 456 | + SDL_SetWindowSize(window, w, h); 457 | + video_settings.xres = w; 458 | + video_settings.yres = h; 459 | + screen_dest_rect.x = 0; 460 | + screen_dest_rect.y = 0; 461 | + screen_dest_rect.w = w; 462 | + screen_dest_rect.h = h; 463 | + screen_w = w; 464 | + screen_h = h; 465 | + ogl_blitter->SetViewport(screen_w, screen_h); 466 | + current_resolution_h = h; 467 | + current_resolution_w = w; 468 | +#else 469 | + // Use SDL video change function - slower 470 | + if(SDL_SetWindowDisplayMode(window, &mode) < 0) 471 | + { 472 | + printf("ERROR - SDL_SetWindowDisplayMode: '%s'\n", SDL_GetError()); 473 | + } 474 | + else 475 | + { 476 | + SDL_SetWindowSize(window, w, h); 477 | + video_settings.xres = w; 478 | + video_settings.yres = h; 479 | + VideoGI->nominal_width = w; 480 | + screen_w = w; 481 | + screen_h = h; 482 | + // screen = SDL_GetWindowSurface(window); 483 | + screen_dest_rect.x = 0; 484 | + screen_dest_rect.y = 0; 485 | + screen_dest_rect.w = w; 486 | + screen_dest_rect.h = h; 487 | + //SDL_GetWindowPosition(window, &x, &y); 488 | + //SDL_PumpEvents(); 489 | + //SDL_SetWindowPosition(window, x, y); 490 | + ogl_blitter->SetViewport(screen_w, screen_h); 491 | + current_resolution_h = h; 492 | + current_resolution_w = w; 493 | + } 494 | +#endif 495 | + } 496 | + printf("VIDEO - Video_ChangeResolution completed\n"); 497 | + } 498 | + } 499 | +} 500 | + 501 | +#ifdef WIN32 502 | +void Video_WinSetVideoMode(int iWidth, int iHeight) 503 | +{ 504 | + DEVMODE Mode; 505 | + printf("EnumDisplaySettings return: %ld\n",EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &Mode)); 506 | + 507 | + //Mode.dmBitsPerPel = iBpp; 508 | + printf("EnumDisplaySettings return refresh rate: %ld\n",Mode.dmDisplayFrequency); 509 | + Mode.dmPelsWidth = iWidth; 510 | + Mode.dmPelsHeight = iHeight; 511 | + Mode.dmSize = sizeof(Mode); 512 | + Mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; 513 | + 514 | + Mode.dmDisplayFrequency = 59.941002; 515 | + 516 | + printf("ChangeDisplaySettings return: %ld\n",ChangeDisplaySettings(&Mode, CDS_FULLSCREEN)); 517 | + 518 | +}; 519 | +#endif 520 | +// SLK - end 521 | + 522 | void Video_Sync(MDFNGI *gi) 523 | { 524 | MDFNI_printf(_("Initializing video...\n")); 525 | @@ -844,6 +1032,41 @@ 526 | 527 | video_settings.shader = (ShaderType)MDFN_GetSettingI(snp + "shader"); 528 | video_settings.shader_str = MDFN_GetSettingS(snp + "shader"); 529 | + 530 | + // SLK - set video settings - disable some options in conflict with native resolution 531 | + _resolution_switch = MDFN_GetSettingI("video.resolution_switch"); 532 | + if(_resolution_switch) 533 | + { 534 | + if(_resolution_switch == RES_NATIVE) // Native Res 535 | + { 536 | + use_native_resolution = true; 537 | + printf("### VIDEO Native resolution init - set to %dx%d\n",resolution_to_change_w,resolution_to_change_h); 538 | + video_settings.xres = resolution_to_change_w; // for fullscreen mode 539 | + VideoGI->nominal_width = resolution_to_change_w; // for windowed mode 540 | + video_settings.xscale = 1; 541 | + video_settings.xscalefs = 1; 542 | + video_settings.yscalefs = 1; 543 | + video_settings.stretch = 0; 544 | + 545 | + } 546 | + if(_resolution_switch == RES_SUPER) 547 | + { 548 | + use_super_resolution = true; 549 | + printf("### VIDEO Super resolution init - set to 2560x%d\n",resolution_to_change_h); 550 | + video_settings.xres = current_resolution_w = 2560; // for fullscreen mode 551 | + VideoGI->nominal_width = 2560; // for windowed mode 552 | + video_settings.xscale = 1; 553 | + video_settings.xscalefs = 1; 554 | + video_settings.yscalefs = 1; 555 | + video_settings.stretch = 0; 556 | + } 557 | + video_settings.yres = current_resolution_h = resolution_to_change_h; // for fullscreen mode 558 | + VideoGI->nominal_height = resolution_to_change_h; // for windowed mode 559 | + video_settings.yscale = 1; 560 | + video_settings.videoip = 0; 561 | + video_settings.shader = SHADER_NONE; 562 | + } 563 | + 564 | // 565 | // 566 | if(0) 567 | @@ -1238,11 +1461,44 @@ 568 | SMRect.y = 0; 569 | SMRect.w = screen_w; 570 | 571 | - SMDRect.w = SMRect.w * xmu; 572 | + // SLK - Set OSD message rendering rect. 573 | + if(use_super_resolution) // enlarge OSD message in super resolution mode 574 | + { 575 | + SMDRect.w = SMRect.w * xmu; 576 | + printf("VIDEO - Init : SMRect.w: %d xmu: %d\n",SMRect.w,xmu); 577 | + } 578 | + else 579 | + { 580 | + SMDRect.w = SMRect.w * xmu; 581 | + } 582 | + // SLK - end 583 | + 584 | + //SMDRect.w = SMRect.w * xmu; 585 | SMDRect.h = SMRect.h * ymu; 586 | SMDRect.x = (screen_w - SMDRect.w) / 2; 587 | - SMDRect.y = screen_h - SMDRect.h; 588 | + // SMDRect.y = screen_h - SMDRect.h; 589 | 590 | + // SLK - Vertical offset for OSD messages 591 | + if(use_native_resolution || use_super_resolution) 592 | + { 593 | + switch(screen_h){ 594 | + case 240:SMDRect.y = screen_h - SMDRect.h - 18; 595 | + break; 596 | + case 288:SMDRect.y = screen_h - SMDRect.h - 32; 597 | + break; 598 | + case 480:SMDRect.y = screen_h - SMDRect.h - 32; 599 | + break; 600 | + case 576:SMDRect.y = screen_h - SMDRect.h - 64; 601 | + break; 602 | + default:SMDRect.y = screen_h - SMDRect.h * xmu; // TODO: ??? 603 | + } 604 | + } 605 | + else 606 | + { 607 | + SMDRect.y = screen_h - SMDRect.h; 608 | + } 609 | + // SLK - end 610 | + 611 | if(SMDRect.x < 0) 612 | { 613 | SMRect.w += SMDRect.x * 2 / xmu; 614 | @@ -1645,9 +1901,25 @@ 615 | src_rect.w = DisplayRect->w; 616 | src_rect.y = DisplayRect->y; 617 | src_rect.h = DisplayRect->h; 618 | - 619 | + 620 | + printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 621 | if(LineWidths[0] == ~0) // Skip multi line widths code? 622 | { 623 | + // SLK - blit for: MD & NES & [...] 624 | + //printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 625 | + //printf(" Dest: %dx%d - %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 626 | + // src_rect.y = (resolution_to_change_h - src_rect.h) / 2 ; //SLK 627 | + if(use_native_resolution || use_super_resolution) 628 | + { 629 | + if(src_rect.w > screen_dest_rect.w) 630 | + { 631 | + src_rect.x = (src_rect.w - screen_dest_rect.w) / 2; 632 | + src_rect.w = screen_dest_rect.w; 633 | + } 634 | + screen_dest_rect.y = (resolution_to_change_h - src_rect.h) / 2; 635 | + screen_dest_rect.h = src_rect.h; 636 | + } 637 | + // SLK end 638 | SubBlit(msurface, src_rect, screen_dest_rect, InterlaceField); 639 | } 640 | else 641 | @@ -1687,25 +1959,68 @@ 642 | } 643 | else 644 | { 645 | - sub_dest_rect.x = screen_dest_rect.x; 646 | - sub_dest_rect.w = screen_dest_rect.w; 647 | - sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 648 | - sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 649 | - } 650 | - 651 | - if(!sub_dest_rect.h) // May occur with small yscale values in certain cases, so prevent triggering an assert() 652 | - sub_dest_rect.h = 1; 653 | + if (use_native_resolution || use_super_resolution) 654 | + { 655 | + // SLK - (prevent) resizing and centering 656 | + // printf(" src_rect: %dx%d - X:%d, Y:%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); 657 | + sub_dest_rect.x = screen_dest_rect.x; 658 | + sub_dest_rect.w = screen_dest_rect.w; 659 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y); // * screen_dest_rect.h / src_rect.h; 660 | + //printf(" sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 661 | + //printf(" sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 662 | + //printf(" sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 663 | + 664 | + if (sub_src_rect.w >= resolution_to_change_w) // horizontal crop to fit screen 665 | + { 666 | + sub_src_rect.x = sub_src_rect.x + ((sub_src_rect.w - resolution_to_change_w) / 2); 667 | + sub_src_rect.w = resolution_to_change_w; 668 | + } 669 | + 670 | + if (native_resolution_vcenter == true) // default vertical centering 671 | + { 672 | + sub_dest_rect.y = sub_dest_rect.y + (resolution_to_change_h - sub_src_rect.h) / 2; 673 | + sub_dest_rect.h = sub_src_rect.h; 674 | + } 675 | + else // fill screen (psx - half black screen fix) 676 | + { 677 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 678 | + } 679 | + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 680 | + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 681 | + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 682 | + } 683 | + else 684 | + { 685 | + sub_dest_rect.x = screen_dest_rect.x; 686 | + sub_dest_rect.w = screen_dest_rect.w; 687 | + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; 688 | + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; 689 | + } 690 | 691 | - // Blit here! 692 | - SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 693 | + if (!sub_dest_rect.h) 694 | + { 695 | + sub_dest_rect.h = 1; 696 | + } // May occur with small yscale values in certain cases, so prevent triggering an assert() 697 | + 698 | + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); 699 | + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); 700 | + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); 701 | + 702 | + 703 | + 704 | + // SLK - end 705 | + 706 | + 707 | + // Blit here! 708 | + SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); 709 | 710 | - last_y = y; 711 | + last_y = y; 712 | 713 | - if(y != (src_rect.y + src_rect.h)) 714 | - { 715 | - last_width = LineWidths[y]; 716 | + if (y != (src_rect.y + src_rect.h)) 717 | + { 718 | + last_width = LineWidths[y]; 719 | + } 720 | } 721 | - 722 | } 723 | } 724 | } 725 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video.h ./emu4crt/src/drivers/video.h 726 | --- ./mednafen/src/drivers/video.h 2019-12-24 04:24:48.000000000 -0800 727 | +++ ./emu4crt/src/drivers/video.h 2020-01-14 14:02:58.847856000 -0800 728 | @@ -36,6 +36,13 @@ 729 | 730 | void Video_Sync(MDFNGI* gi); 731 | 732 | +// SLK 733 | +void Video_ChangeResolution(MDFNGI* gi, int w, int h); 734 | +#ifdef WIN32 735 | +void Video_WinSetVideoMode(int iWidth, int iHeight); 736 | +#endif 737 | +// SLK 738 | + 739 | void Video_Exposed(void); 740 | 741 | void Video_Kill(void) MDFN_COLD; 742 | diff -Naur -r --no-dereference ./mednafen/src/drivers/video-state.cpp ./emu4crt/src/drivers/video-state.cpp 743 | --- ./mednafen/src/drivers/video-state.cpp 2019-12-24 04:24:48.000000000 -0800 744 | +++ ./emu4crt/src/drivers/video-state.cpp 2019-12-26 07:31:19.375343000 -0800 745 | @@ -161,7 +161,7 @@ 746 | } // end if(StateStatus) 747 | 748 | if(PreviewSurface) 749 | - { 750 | +{ 751 | MDFN_Rect tdrect, drect; 752 | 753 | int meow = ((screen_w / CurGame->nominal_width) + 1) / 2; 754 | @@ -169,19 +169,51 @@ 755 | 756 | tdrect.w = TextRect.w * meow; 757 | tdrect.h = TextRect.h * meow; 758 | - tdrect.x = (screen_w - tdrect.w) / 2; 759 | - tdrect.y = screen_h - tdrect.h; 760 | - 761 | - BlitRaw(TextSurface, &TextRect, &tdrect); 762 | - 763 | - drect.w = PreviewRect.w * meow; 764 | - drect.h = PreviewRect.h * meow; 765 | - drect.x = (screen_w - drect.w) / 2; 766 | - drect.y = screen_h - drect.h - tdrect.h - 4; 767 | - 768 | - BlitRaw(PreviewSurface, &PreviewRect, &drect); 769 | - 770 | - } 771 | + tdrect.x = (screen_w - tdrect.w) / 2; 772 | + // SLK - Custom savestate selection OSD 773 | + if(use_native_resolution || use_super_resolution) 774 | + { 775 | + switch(screen_h){ 776 | + case 240:tdrect.y = screen_h - tdrect.h - 18; 777 | + break; 778 | + case 288:tdrect.y = screen_h - tdrect.h - 32; 779 | + break; 780 | + case 480:tdrect.y = screen_h - tdrect.h - 32; 781 | + break; 782 | + case 576:tdrect.y = screen_h - tdrect.h - 64; 783 | + break; 784 | + default:tdrect.y = screen_h - tdrect.h; 785 | + } 786 | + if(use_super_resolution) 787 | + { 788 | + tdrect.w = tdrect.w * 8; 789 | + tdrect.x = (screen_w - tdrect.w) / 2; 790 | + } 791 | + 792 | + BlitRaw(TextSurface, &TextRect, &tdrect); 793 | + 794 | + drect.w = screen_w * 0.5 + 3; // TODO: Why 3 ??? 795 | + drect.h = screen_h * 0.5 + 3; 796 | + drect.x = (screen_w - drect.w) / 2; 797 | + drect.y = tdrect.y - drect.h; // SLK 798 | + 799 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 800 | + } 801 | + else // native OSD display 802 | + { 803 | + tdrect.y = screen_h - tdrect.h; 804 | + 805 | + BlitRaw(TextSurface, &TextRect, &tdrect); 806 | + 807 | + drect.w = PreviewRect.w * meow; 808 | + drect.h = PreviewRect.h * meow; 809 | + drect.x = (screen_w - drect.w) / 2; 810 | + drect.y = screen_h - drect.h - tdrect.h - 4; 811 | + 812 | + BlitRaw(PreviewSurface, &PreviewRect, &drect); 813 | + } 814 | + // SLK - end 815 | + } 816 | 817 | } 818 | 819 | diff -Naur -r --no-dereference ./mednafen/src/md/system.cpp ./emu4crt/src/md/system.cpp 820 | --- ./mednafen/src/md/system.cpp 2019-12-24 04:24:48.000000000 -0800 821 | +++ ./emu4crt/src/md/system.cpp 2020-01-19 04:58:35.337691464 -0800 822 | @@ -90,7 +90,15 @@ 823 | #ifdef WANT_DEBUGGER 824 | MDDBG_Init(); 825 | #endif 826 | - 827 | + // SLK 828 | + if(MDFN_GetSettingUI("video.resolution_switch") != 0) 829 | + { 830 | + printf("MD - SYSTEM - Init screen resolution to 320x240\n"); 831 | + resolution_to_change_w = 320; 832 | + resolution_to_change_h = 240; 833 | + resolution_to_change = true; 834 | + } 835 | + // SLK - end 836 | } 837 | 838 | static void system_reset(bool poweron) 839 | diff -Naur -r --no-dereference ./mednafen/src/md/vdp.cpp ./emu4crt/src/md/vdp.cpp 840 | --- ./mednafen/src/md/vdp.cpp 2019-12-24 04:24:48.000000000 -0800 841 | +++ ./emu4crt/src/md/vdp.cpp 2020-01-19 08:57:17.684016527 -0800 842 | @@ -53,6 +53,13 @@ 843 | 0x40404040, 0x50505050, 0x60606060, 0x70707070 844 | }; 845 | 846 | +// SLK 847 | +static int prev_w = 0; 848 | +static int prev_h = 0; 849 | +static bool prev_is_pal = false; 850 | +static bool prev_i = false; 851 | +//SLK end 852 | + 853 | MDVDP::MDVDP() 854 | { 855 | int bx, ax, i; 856 | @@ -108,6 +115,42 @@ 857 | 858 | bitmap.viewport.changed = 1; 859 | #endif 860 | +// SLK 861 | +printf("MD - VDP - Video mode w: %dx%d\n",((reg[0xC] & 0x1) ? 320 : 256),(reg[0x1] & 0x8) ? 240 : 224); 862 | +//printf("MD - VDP - Video mode h: %d\n",((reg[0x1] & 0x8) ? 240 : 224)); 863 | +printf("MD - VDP - Interlace: %s\n", ((reg[0xC] & 0x06) == 0x06) ? "ON" : "OFF"); 864 | +printf("MD - VDP - Region standard: %s\n", (is_pal) ? "PAL" : "NTSC"); 865 | +native_resolution_vcenter = false; 866 | +int cur_w = ((reg[0xC] & 0x1) ? 320 : 256); 867 | +int cur_h = 0; 868 | +int cur_i = ((reg[0xC] & 0x06) == 0x06) ? true : false; 869 | + 870 | +if(is_pal) 871 | +{ 872 | + cur_h = cur_i ? 576 : 288; 873 | +} 874 | +else 875 | +{ 876 | + cur_h = cur_i ? 480 : 240; 877 | +} 878 | +if(prev_w != cur_w){ 879 | + resolution_to_change_w = cur_w; 880 | + prev_w = cur_w; 881 | + resolution_to_change = true; 882 | +} 883 | +if(cur_h != prev_h){ 884 | + resolution_to_change_h = cur_h; 885 | + prev_h = cur_h; 886 | + resolution_to_change = true; 887 | +} 888 | + 889 | +printf(" MD - VDP - next Video mode w: %dx%d\n",cur_w,cur_h); 890 | +//printf("MD - VDP - Video mode h: %d\n",((reg[0x1] & 0x8) ? 240 : 224)); 891 | +//printf("MD - VDP - next Interlace: %s\n", ((reg[0xC] & 0x06) == 0x06) ? "ON" : "OFF"); 892 | +printf(" MD - VDP - next Region standard: %s\n", (is_pal) ? "PAL" : "NTSC"); 893 | + 894 | + 895 | +// SLK - end 896 | } 897 | 898 | void MDVDP::SyncColors(void) 899 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.cpp ./emu4crt/src/mednafen.cpp 900 | --- ./mednafen/src/mednafen.cpp 2019-12-24 04:24:48.000000000 -0800 901 | +++ ./emu4crt/src/mednafen.cpp 2020-01-11 19:02:13.691141000 -0800 902 | @@ -51,6 +51,18 @@ 903 | #include "video/tblur.h" 904 | #include "qtrecord.h" 905 | 906 | +// SLK 907 | +bool use_native_resolution = false; 908 | +bool use_super_resolution = false; 909 | +bool resolution_to_change; 910 | +int resolution_to_change_w; 911 | +int resolution_to_change_h; 912 | +int current_resolution_w; 913 | +int current_resolution_h; 914 | +bool native_resolution_vcenter = true; 915 | +// SLK end 916 | + 917 | + 918 | namespace Mednafen 919 | { 920 | 921 | @@ -1261,7 +1273,7 @@ 922 | throw MDFN_Error(0, _("Unrecognized file format.")); 923 | } 924 | 925 | - MDFN_printf(_("Using module: %s(%s)\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); 926 | + MDFN_printf(_("Using module:%s (%s)\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); 927 | { 928 | MDFN_AutoIndent aindentgm(1); 929 | 930 | diff -Naur -r --no-dereference ./mednafen/src/mednafen.h ./emu4crt/src/mednafen.h 931 | --- ./mednafen/src/mednafen.h 2019-12-24 04:24:48.000000000 -0800 932 | +++ ./emu4crt/src/mednafen.h 2020-01-12 13:00:27.436983000 -0800 933 | @@ -21,6 +21,18 @@ 934 | #include "settings.h" 935 | #include "NativeVFS.h" 936 | 937 | +// SLK 938 | +extern bool use_native_resolution; 939 | +extern bool use_super_resolution; 940 | +extern bool native_resolution_vcenter; 941 | +extern bool resolution_to_change; 942 | +extern int resolution_to_change_w; 943 | +extern int resolution_to_change_h; 944 | +extern int current_resolution_w; 945 | +extern int current_resolution_h; 946 | +// SLK end 947 | + 948 | + 949 | namespace Mednafen 950 | { 951 | MDFN_HIDE extern NativeVFS NVFS; 952 | diff -Naur -r --no-dereference ./mednafen/src/nes/nes.cpp ./emu4crt/src/nes/nes.cpp 953 | --- ./mednafen/src/nes/nes.cpp 2019-12-24 04:24:48.000000000 -0800 954 | +++ ./emu4crt/src/nes/nes.cpp 2019-12-26 07:31:19.375343000 -0800 955 | @@ -287,7 +287,21 @@ 956 | MDFNGameInfo->fps = PAL? 838977920 : 1008307711; 957 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); 958 | } 959 | - 960 | + 961 | + //SLK 962 | + if(PAL) 963 | + { 964 | + resolution_to_change_h = 288; 965 | + } 966 | + else 967 | + { 968 | + resolution_to_change_h = 240; 969 | + } 970 | + resolution_to_change_w = 256; 971 | + resolution_to_change = true; 972 | + //SLK end 973 | + 974 | + 975 | X6502_Init(); 976 | MDFNPPU_Init(); 977 | MDFNSND_Init(PAL); 978 | diff -Naur -r --no-dereference ./mednafen/src/pce/pce.cpp ./emu4crt/src/pce/pce.cpp 979 | --- ./mednafen/src/pce/pce.cpp 2019-12-24 04:24:48.000000000 -0800 980 | +++ ./emu4crt/src/pce/pce.cpp 2019-12-26 07:31:19.379343000 -0800 981 | @@ -414,6 +414,16 @@ 982 | for(unsigned ch = 0; ch < 2; ch++) 983 | HRBufs[ch] = new OwlBuffer(); 984 | 985 | + // SLK 986 | + if(MDFN_GetSettingB("pce.arcadecard")) 987 | + { 988 | + resolution_to_change_w = 256; 989 | + resolution_to_change_h = 240; 990 | + resolution_to_change = true; 991 | + } 992 | + // SLK 993 | + 994 | + 995 | // FIXME: Make these globals less global! 996 | PCE_ACEnabled = MDFN_GetSettingB("pce.arcadecard"); 997 | 998 | diff -Naur -r --no-dereference ./mednafen/src/pce/vce.cpp ./emu4crt/src/pce/vce.cpp 999 | --- ./mednafen/src/pce/vce.cpp 2019-12-24 04:24:48.000000000 -0800 1000 | +++ ./emu4crt/src/pce/vce.cpp 2019-12-26 07:31:19.379343000 -0800 1001 | @@ -35,6 +35,11 @@ 1002 | namespace MDFN_IEN_PCE 1003 | { 1004 | 1005 | +// SLK 1006 | +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start 1007 | +static const int width_list[4] = {256, 320, 512, 512 }; // SLK 1008 | +// SLK end 1009 | + 1010 | static const int vce_ratios[4] = { 4, 3, 2, 2 }; 1011 | 1012 | static MDFN_FASTCALL NO_INLINE int32 Sync(const int32 timestamp); 1013 | @@ -634,6 +639,18 @@ 1014 | dot_clock_ratio = vce_ratios[dot_clock]; 1015 | 1016 | CR = V; 1017 | + 1018 | + // SLK 1019 | + if(dot_clock != prev_dot_clock) 1020 | + { 1021 | + printf("PCE - VCE - dot_clock change to: %d\n",dot_clock); 1022 | + prev_dot_clock = dot_clock; 1023 | + resolution_to_change_w = width_list[dot_clock]; 1024 | + resolution_to_change_h = 240; 1025 | + resolution_to_change = true; 1026 | + } 1027 | + // SLK end 1028 | + 1029 | } 1030 | 1031 | void VCE::SetPixelFormat(const MDFN_PixelFormat &format, const uint8* CustomColorMap, const uint32 CustomColorMapLen) 1032 | diff -Naur -r --no-dereference ./mednafen/src/pce_fast/pce.cpp ./emu4crt/src/pce_fast/pce.cpp 1033 | --- ./mednafen/src/pce_fast/pce.cpp 2019-12-24 04:24:48.000000000 -0800 1034 | +++ ./emu4crt/src/pce_fast/pce.cpp 2020-01-19 04:56:49.680470244 -0800 1035 | @@ -290,6 +290,16 @@ 1036 | { 1037 | HuC6280_Init(); 1038 | 1039 | + // SLK - TODO find a better place for this 1040 | + if(MDFN_GetSettingUI("video.resolution_switch") != 0) 1041 | + { 1042 | + printf("PCE FAST - Init resolution to 256x240\n"); 1043 | + resolution_to_change_w = 256; 1044 | + resolution_to_change_h = 240; 1045 | + resolution_to_change = true; 1046 | + } 1047 | + // SLK 1048 | + 1049 | // FIXME: Make these globals less global! 1050 | pce_overclocked = MDFN_GetSettingUI("pce_fast.ocmultiplier"); 1051 | PCE_ACEnabled = MDFN_GetSettingB("pce_fast.arcadecard"); 1052 | diff -Naur -r --no-dereference ./mednafen/src/pce_fast/vdc.cpp ./emu4crt/src/pce_fast/vdc.cpp 1053 | --- ./mednafen/src/pce_fast/vdc.cpp 2019-12-24 04:24:48.000000000 -0800 1054 | +++ ./emu4crt/src/pce_fast/vdc.cpp 2020-01-19 04:21:59.399187284 -0800 1055 | @@ -53,6 +53,11 @@ 1056 | int VDC_TotalChips; 1057 | vdc_t vdc_chips[2]; 1058 | 1059 | +// SLK 1060 | +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start 1061 | +static const int width_list[4] = {256, 320, 512, 512 }; // SLK 1062 | +// SLK - end 1063 | + 1064 | static INLINE void FixPCache(int entry) 1065 | { 1066 | const uint32* __restrict__ cm32 = systemColorMap32[vce.CR >> 7]; 1067 | @@ -655,6 +660,18 @@ 1068 | end += 128; 1069 | start += 128; 1070 | 1071 | + // SLK 1072 | + if(vce.dot_clock != prev_dot_clock) 1073 | + { 1074 | + printf("PCE FAST - VCE - dot_clock changed from %d to %d\n",prev_dot_clock,vce.dot_clock); 1075 | + prev_dot_clock = vce.dot_clock; 1076 | + resolution_to_change_w = width_list[vce.dot_clock]; 1077 | + resolution_to_change_h = 240; 1078 | + resolution_to_change = true; 1079 | + } 1080 | + // SLK END 1081 | + 1082 | + 1083 | #if 0 1084 | uint32 display_width; 1085 | display_width = (M_vdc_HDW + 1) * 8; 1086 | diff -Naur -r --no-dereference ./mednafen/src/pcfx/king.cpp ./emu4crt/src/pcfx/king.cpp 1087 | --- ./mednafen/src/pcfx/king.cpp 2019-12-24 04:24:48.000000000 -0800 1088 | +++ ./emu4crt/src/pcfx/king.cpp 2020-03-12 16:31:11.831495708 -0700 1089 | @@ -58,6 +58,7 @@ 1090 | #define ADPCMDBG(format, ...) (void)0 1091 | //FXDBG 1092 | 1093 | + 1094 | /* 1095 | SCSI Questions(this list needs to be revised more and merged into the issues list at the beginning of the file): 1096 | 1097 | @@ -203,8 +204,6 @@ 1098 | // 8 * 2 for left + right padding for scrolling 1099 | alignas(8) static uint32 bg_linebuffer[256 + 8 + 8]; 1100 | 1101 | - 1102 | - 1103 | // Don't change these enums, there are some hardcoded values still used(particularly, LAYER_NONE). 1104 | enum 1105 | { 1106 | @@ -1734,6 +1733,11 @@ 1107 | static uint32 HighDotClockWidth; 1108 | extern RavenBuffer* FXCDDABufs[2]; // FIXME, externals are evil! 1109 | 1110 | +// SLK 1111 | +int prev_dot_clock = 0; 1112 | +bool prev_frame_interlaced = false; 1113 | +// SLK - end 1114 | + 1115 | static void Cleanup(void) 1116 | { 1117 | if(king) 1118 | @@ -1754,7 +1758,17 @@ 1119 | 1120 | king->lastts = 0; 1121 | 1122 | - HighDotClockWidth = MDFN_GetSettingUI("pcfx.high_dotclock_width"); 1123 | + // SLK 1124 | + if (use_super_resolution || use_native_resolution) 1125 | + { 1126 | + printf("KING_Init - Use super or native resolution\n"); 1127 | + HighDotClockWidth = 256; 1128 | + } 1129 | + else 1130 | + { 1131 | + HighDotClockWidth = MDFN_GetSettingUI("pcfx.high_dotclock_width"); 1132 | + } 1133 | + // SLK - end 1134 | BGLayerDisable = 0; 1135 | 1136 | BuildCMT(); 1137 | @@ -2496,6 +2510,23 @@ 1138 | DisplayRect->y *= 2; 1139 | DisplayRect->h *= 2; 1140 | } 1141 | + // SLK 1142 | + if(fx_vce.dot_clock != prev_dot_clock || prev_frame_interlaced != fx_vce.frame_interlaced) 1143 | + { 1144 | + printf("PCFX - KING_StartFrame\n"); 1145 | + printf("PCFX - HighDotClockWidth: %d\n",HighDotClockWidth); 1146 | + printf("PCFX - fx_vce.dot_clock: %d\n",fx_vce.dot_clock); 1147 | + 1148 | + resolution_to_change_w = (fx_vce.dot_clock) ? 344 : 256; 1149 | + resolution_to_change_h = (fx_vce.frame_interlaced) ? 480 : 240; 1150 | + 1151 | + prev_dot_clock = fx_vce.dot_clock; 1152 | + prev_frame_interlaced = fx_vce.frame_interlaced; 1153 | + 1154 | + //HighDotClockWidth = 341; // Why ??? 1155 | + resolution_to_change = true; 1156 | + } 1157 | + // SLK - end 1158 | } 1159 | 1160 | static int rb_type; 1161 | diff -Naur -r --no-dereference ./mednafen/src/pcfx/king.h ./emu4crt/src/pcfx/king.h 1162 | --- ./mednafen/src/pcfx/king.h 2019-12-24 04:24:48.000000000 -0800 1163 | +++ ./emu4crt/src/pcfx/king.h 2020-03-10 15:49:21.853116323 -0700 1164 | @@ -25,6 +25,7 @@ 1165 | namespace MDFN_IEN_PCFX 1166 | { 1167 | 1168 | + 1169 | // 1170 | // Be sure to keep the numbered/lettered *_GSREG_* registers(MPROG0*, AFFIN*, etc.) here in contiguous sequential order(since we do stuff like "- KING_GSREG_MPROG0" 1171 | // in king.cpp. 1172 | diff -Naur -r --no-dereference ./mednafen/src/pcfx/pcfx.cpp ./emu4crt/src/pcfx/pcfx.cpp 1173 | --- ./mednafen/src/pcfx/pcfx.cpp 2019-12-24 04:24:48.000000000 -0800 1174 | +++ ./emu4crt/src/pcfx/pcfx.cpp 2020-03-12 16:19:45.683867201 -0700 1175 | @@ -651,7 +651,18 @@ 1176 | if(WantHuC6273) 1177 | HuC6273_Init(); 1178 | 1179 | - KING_Init(); 1180 | + // SLK 1181 | + 1182 | + printf("PCFX - pcfx - use native or super resolution\n"); 1183 | + native_resolution_vcenter = false; 1184 | + resolution_to_change = true; 1185 | + resolution_to_change_w = 256; 1186 | + resolution_to_change_h = 240; 1187 | + // SLK - END 1188 | + 1189 | +KING_Init(); 1190 | + 1191 | + 1192 | 1193 | SCSICD_SetDisc(true, NULL, true); 1194 | 1195 | diff -Naur -r --no-dereference ./mednafen/src/psx/gpu.cpp ./emu4crt/src/psx/gpu.cpp 1196 | --- ./mednafen/src/psx/gpu.cpp 2019-12-24 04:24:48.000000000 -0800 1197 | +++ ./emu4crt/src/psx/gpu.cpp 2020-01-11 19:26:12.184709000 -0800 1198 | @@ -24,6 +24,7 @@ 1199 | #include "psx.h" 1200 | #include "timer.h" 1201 | 1202 | +#include // SLK 1203 | /* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ 1204 | 1205 | /* 1206 | @@ -74,6 +75,79 @@ 1207 | } 1208 | using namespace PS_GPU_INTERNAL; 1209 | 1210 | +// SLK 1211 | +uint32 PreviousDisplayMode; 1212 | +int prev_resolution_w; 1213 | +int prev_resolution_h; 1214 | +int res_change_count; 1215 | + 1216 | + 1217 | +void GPU_NewDisplayMode(int V) // SLK - identify GPU new resolution, set global variables used in MAIN & VIDEO 1218 | +{ 1219 | + // GP1(08h) - Display mode 1220 | + // 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 1221 | + // 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 1222 | + // 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 1223 | + // 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 1224 | + // 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 1225 | + // 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 1226 | + // 7 "Reverseflag" (0=Normal, 1=Distorted) ;GPUSTAT.14 1227 | + // source: http://problemkaputt.de/psx-spx.txt 1228 | + 1229 | + // Width 1230 | + if((V & 0x40) == 0x40) 1231 | + { 1232 | + resolution_to_change_w = 368; 1233 | + } 1234 | + else 1235 | + { 1236 | + switch(V & 0x3) 1237 | + { 1238 | + case 0x00: 1239 | + resolution_to_change_w = 256; 1240 | + break; 1241 | + case 0x01: 1242 | + resolution_to_change_w = 320; 1243 | + break; 1244 | + case 0x02: 1245 | + resolution_to_change_w = 512; 1246 | + break; 1247 | + case 0x03: 1248 | + resolution_to_change_w = 640; 1249 | + break; 1250 | + } 1251 | + } 1252 | + // Height 1253 | + if ((V & 8) == 8) 1254 | + { //PAL 1255 | + if ((V & 32) == 32) {resolution_to_change_h = 576;} //5 1256 | + else {resolution_to_change_h = 288;} 1257 | + } 1258 | + else 1259 | + { // NTSC 1260 | + if ((V & 32) == 32){resolution_to_change_h = 480;} //5 1261 | + else {resolution_to_change_h = 240;} 1262 | + } 1263 | + 1264 | + if(prev_resolution_w != resolution_to_change_w || prev_resolution_h != resolution_to_change_h) 1265 | + { 1266 | + if(res_change_count < 2) 1267 | + { 1268 | + res_change_count += 1; 1269 | + printf("PSX GPU - Startup resolution change bypass (%d).\n",res_change_count); 1270 | + native_resolution_vcenter = false; // No need Vertical centering for PSX module. 1271 | + } 1272 | + else{ 1273 | + prev_resolution_w = resolution_to_change_w; // will be used in VIDEO.cpp 1274 | + prev_resolution_h = resolution_to_change_h; 1275 | + printf("PSX - GPU register - resolution change to: %dx%d (V=%d)\n",resolution_to_change_w,resolution_to_change_h,V); 1276 | + resolution_to_change = true; // will be reset in VIDEO.cpp 1277 | + 1278 | + } 1279 | + } 1280 | +} 1281 | +// SLK end 1282 | + 1283 | void GPU_Init(bool pal_clock_and_tv) 1284 | { 1285 | static const int8 dither_table[4][4] = 1286 | @@ -110,11 +184,25 @@ 1287 | { 1288 | GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) 1289 | hmc_to_visible = 520; 1290 | + 1291 | + //SLK 1292 | + resolution_to_change = true; 1293 | + resolution_to_change_w = 640; 1294 | + resolution_to_change_h = 480; 1295 | + printf("PSX - GPU Init - NTSC mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1296 | + 1297 | } 1298 | else // PAL clock 1299 | { 1300 | GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) 1301 | hmc_to_visible = 560; 1302 | + 1303 | + //SLK 1304 | + resolution_to_change = true; 1305 | + resolution_to_change_w = 640; 1306 | + resolution_to_change_h = 576; 1307 | + printf("PSX - GPU Init - PAL mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1308 | + 1309 | } 1310 | 1311 | memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); 1312 | @@ -905,6 +993,11 @@ 1313 | case 0x08: 1314 | //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); 1315 | DisplayMode = V & 0xFF; 1316 | + if(PreviousDisplayMode != DisplayMode) // SLK - Trap GPU resolution change 1317 | + { 1318 | + PreviousDisplayMode = DisplayMode; 1319 | + GPU_NewDisplayMode(V); 1320 | + } 1321 | break; 1322 | 1323 | case 0x09: 1324 | @@ -1118,8 +1211,13 @@ 1325 | MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp) 1326 | { 1327 | const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); 1328 | - const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) 1329 | - const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo 1330 | + 1331 | + // SLK - Hotdog mod 1/2 - Fix Horizontal centering & cropping 1332 | + //const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) 1333 | + //const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo 1334 | + const uint32 dmw = 2560 / DotClockRatios[dmc]; // Must be <= (768 - 32) 1335 | + const uint32 dmpa = 0; 1336 | +// SLK - Hotdog mod 1/2 - end 1337 | 1338 | int32 sys_clocks = sys_timestamp - lastts; 1339 | int32 gpu_clocks; 1340 | @@ -1273,7 +1371,7 @@ 1341 | char buffer[256]; 1342 | trio_snprintf(buffer, sizeof(buffer), _("VIDEO STANDARD MISMATCH")); 1343 | DrawText(surface, 0, (DisplayRect->h / 2) - (13 / 2), buffer, 1344 | - surface->MakeColor(0x00, 0xFF, 0x00), MDFN_FONT_6x13_12x13, DisplayRect->w); 1345 | + surface->MakeColor(0x00, 0xFF, 0x00), MDFN_FONT_6x13_12x13, DisplayRect->w); 1346 | } 1347 | } 1348 | else 1349 | @@ -1293,8 +1391,8 @@ 1350 | 1351 | for(int i = 0; i < (DisplayRect->y + DisplayRect->h); i++) 1352 | { 1353 | - surface->pixels[i * surface->pitch32 + drxbo + 0] = 1354 | - surface->pixels[i * surface->pitch32 + drxbo + 1] = black; 1355 | + surface->pixels[i * surface->pitch32 + drxbo + 0] = 1356 | + surface->pixels[i * surface->pitch32 + drxbo + 1] = black; 1357 | LineWidths[i] = 2; 1358 | } 1359 | } 1360 | @@ -1370,16 +1468,35 @@ 1361 | dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 1362 | dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 1363 | 1364 | + 1365 | + // SLK - Hotdog mod 2/2 - Fix horizontal centering & cropping 1366 | + int32 actualGameBufferWidth = (HorizEnd - HorizStart) / DotClockRatios[dmc]; 1367 | + int32 ourBufferWidth = dmw; 1368 | + 1369 | + int32 leftOffset = (actualGameBufferWidth - ourBufferWidth) / 2; 1370 | + //leftOffset *= DotClockRatios[dmc]; // Get back into PSX GPU co-ords. 1371 | + leftOffset = std::max(leftOffset, 0); // Make sure not negative 1372 | + dx_start += leftOffset; // Offset the PSX buffer to render relative to our frame. 1373 | + // 1374 | + 1375 | + dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; 1376 | + dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; 1377 | + 1378 | if(dx_end < dx_start) 1379 | dx_end = dx_start; 1380 | 1381 | dx_start = dx_start / DotClockRatios[dmc]; 1382 | dx_end = dx_end / DotClockRatios[dmc]; 1383 | 1384 | - dx_start -= hmc_to_visible / DotClockRatios[dmc]; 1385 | - dx_end -= hmc_to_visible / DotClockRatios[dmc]; 1386 | - dx_start += 7; 1387 | - dx_end += 7; 1388 | + dx_end -= dx_start; 1389 | + dx_start = -leftOffset; 1390 | + 1391 | + // dx_start -= hmc_to_visible / DotClockRatios[dmc]; 1392 | + // dx_end -= hmc_to_visible / DotClockRatios[dmc]; 1393 | + // dx_start += 7; 1394 | + // dx_end += 7; 1395 | + 1396 | + // SLK - Hotdog mod 2/2 - end 1397 | 1398 | if(dx_start < 0) 1399 | { 1400 | @@ -1462,7 +1579,7 @@ 1401 | } // end while(gpu_clocks > 0) 1402 | 1403 | //puts("GPU Update End"); 1404 | - 1405 | + 1406 | TheEnd: 1407 | lastts = sys_timestamp; 1408 | 1409 | diff -Naur -r --no-dereference ./mednafen/src/psx/psx.cpp ./emu4crt/src/psx/psx.cpp 1410 | --- ./mednafen/src/psx/psx.cpp 2019-12-24 04:24:48.000000000 -0800 1411 | +++ ./emu4crt/src/psx/psx.cpp 2020-01-09 15:39:25.370977000 -0800 1412 | @@ -1129,6 +1129,9 @@ 1413 | if(!espec->skip) 1414 | { 1415 | espec->LineWidths[0] = ~0; 1416 | + // SLK 1417 | + espec->DisplayRect.x = espec->DisplayRect.x + (espec->DisplayRect.w * 0.046875); 1418 | + // SLK 1419 | Player_Draw(espec->surface, &espec->DisplayRect, 0, espec->SoundBuf, espec->SoundBufSize); 1420 | } 1421 | } 1422 | diff -Naur -r --no-dereference ./mednafen/src/sms/cart.cpp ./emu4crt/src/sms/cart.cpp 1423 | --- ./mednafen/src/sms/cart.cpp 2019-12-24 04:24:48.000000000 -0800 1424 | +++ ./emu4crt/src/sms/cart.cpp 2020-03-22 15:58:41.089461521 -0700 1425 | @@ -24,6 +24,8 @@ 1426 | 1427 | #include 1428 | 1429 | +#include // SLK 1430 | + 1431 | namespace MDFN_IEN_SMS 1432 | { 1433 | 1434 | @@ -149,6 +151,14 @@ 1435 | MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str()); 1436 | MDFN_printf(_("Mapper: %s\n"), sms_mapper_string_table[mapper]); 1437 | MDFN_printf(_("Territory: %s\n"), (sms.territory == TERRITORY_DOMESTIC) ? _("Domestic") : _("Export")); 1438 | + 1439 | + 1440 | + MDFN_printf(_("SMS - system - PAL vs NTSC: %s\n"),sms.display); 1441 | + // SLK 1442 | + resolution_to_change_h = (sms.display) ? 288 : 240; 1443 | + resolution_to_change_w = 256; 1444 | + resolution_to_change = true; 1445 | + // SLK - end 1446 | } 1447 | 1448 | void Cart_LoadNV(void) 1449 | diff -Naur -r --no-dereference ./mednafen/src/sms/system.cpp ./emu4crt/src/sms/system.cpp 1450 | --- ./mednafen/src/sms/system.cpp 2019-12-24 04:24:48.000000000 -0800 1451 | +++ ./emu4crt/src/sms/system.cpp 2020-03-16 17:10:29.593386513 -0700 1452 | @@ -19,6 +19,8 @@ 1453 | #include "shared.h" 1454 | #include 1455 | 1456 | + 1457 | + 1458 | namespace MDFN_IEN_SMS 1459 | { 1460 | 1461 | @@ -232,7 +234,7 @@ 1462 | render_init(); 1463 | 1464 | uint32 sndclk; 1465 | - 1466 | + 1467 | if(sms.display == DISPLAY_PAL) 1468 | { 1469 | sndclk = 3546893; 1470 | diff -Naur -r --no-dereference ./mednafen/src/snes/interface.cpp ./emu4crt/src/snes/interface.cpp 1471 | --- ./mednafen/src/snes/interface.cpp 2019-12-24 04:24:48.000000000 -0800 1472 | +++ ./emu4crt/src/snes/interface.cpp 2020-01-01 05:54:16.407604000 -0800 1473 | @@ -73,6 +73,11 @@ 1474 | 1475 | static std::vector ColorMap; // [32768] 1476 | 1477 | +// SLK 1478 | +int prev_resolution_w; 1479 | +int prev_resolution_h; 1480 | +// SLK - end 1481 | + 1482 | static void BuildColorMap(MDFN_PixelFormat &format, uint8* CustomColorMap) 1483 | { 1484 | for(int x = 0; x < 32768; x++) 1485 | @@ -545,6 +550,23 @@ 1486 | MDFNGameInfo->fps = PAL ? 838977920 : 1008307711; 1487 | MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(32040.5); 1488 | 1489 | + // SLK - init. dynamic display video resolution - progressive by default 1490 | + printf("SNES Interface - Regional mode: %s \n",(PAL ? "PAL" : "NTSC")); 1491 | + if(PAL) 1492 | + { 1493 | + resolution_to_change_h = 288; 1494 | + } 1495 | + else 1496 | + { 1497 | + printf(" Video mode set to 256 x 240\n"); 1498 | + resolution_to_change_h = 240; 1499 | + } 1500 | + resolution_to_change_w = 256; 1501 | + resolution_to_change = true; 1502 | + prev_resolution_w = resolution_to_change_w; 1503 | + prev_resolution_h = resolution_to_change_h; 1504 | + // SLK - end 1505 | + 1506 | if(!snsf_loader) 1507 | { 1508 | EnableHBlend = MDFN_GetSettingB("snes.h_blend"); 1509 | @@ -889,6 +911,32 @@ 1510 | bSNES_v059::system.run_mednafen_custom(); 1511 | bSNES_v059::ppu.enable_renderer(true); 1512 | 1513 | + // SLK - guess SNES active resolution 1514 | + //printf("SNES Interface - Emulate - %dx%d - %d,%d\n",tdr->w,tdr->h,tdr->x,tdr->y); 1515 | + if(tdr->h > 10 && tdr->w > 10 && tdr->w != prev_resolution_w) 1516 | + { 1517 | + resolution_to_change = true; 1518 | + resolution_to_change_w = tdr->w; 1519 | + } 1520 | + if(tdr->h > 10 && tdr->w > 10 && tdr->h != prev_resolution_h) 1521 | + { 1522 | + resolution_to_change = true; 1523 | + if(tdr->h <= 400) 1524 | + { 1525 | + resolution_to_change_h = bSNES_v059::system.region() ? 288 : 240; 1526 | + } 1527 | + else 1528 | + { 1529 | + resolution_to_change_h = bSNES_v059::system.region() ? 576 : 480; 1530 | + } 1531 | + } 1532 | + if(resolution_to_change) 1533 | + { 1534 | + //printf("SNES - Interface - Resolution change detected: %dx%d\n",resolution_to_change_w,resolution_to_change_h); 1535 | + prev_resolution_w = resolution_to_change_w; 1536 | + prev_resolution_h = tdr->h; 1537 | + } 1538 | + // SLK - end 1539 | 1540 | // 1541 | // Blank out any missed lines(for e.g. display height change with PAL emulation) 1542 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_common.h ./emu4crt/src/snes_faust/ppu_common.h 1543 | --- ./mednafen/src/snes_faust/ppu_common.h 2019-12-24 04:24:48.000000000 -0800 1544 | +++ ./emu4crt/src/snes_faust/ppu_common.h 2020-01-12 12:59:54.692893000 -0800 1545 | @@ -21,5 +21,4 @@ 1546 | void PPU_PokeCGRAM(uint32 addr, uint16 val) MDFN_COLD; 1547 | void PPU_PokeOAM(uint32 addr, uint8 val) MDFN_COLD; 1548 | void PPU_PokeOAMHI(uint32 addr, uint8 val) MDFN_COLD; 1549 | -void PPU_SetRegister(const unsigned id, const uint32 value) MDFN_COLD; 1550 | - 1551 | +void PPU_SetRegister(const unsigned id, const uint32 value) MDFN_COLD; 1552 | \ No newline at end of file 1553 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mt.cpp ./emu4crt/src/snes_faust/ppu_mt.cpp 1554 | --- ./mednafen/src/snes_faust/ppu_mt.cpp 2019-12-24 04:24:48.000000000 -0800 1555 | +++ ./emu4crt/src/snes_faust/ppu_mt.cpp 2020-01-01 14:56:52.304295000 -0800 1556 | @@ -43,6 +43,12 @@ 1557 | namespace PPU_MT 1558 | { 1559 | 1560 | +// SLK 1561 | +int prev_resolution_w; 1562 | +int prev_resolution_h; 1563 | +// SLK 1564 | + 1565 | + 1566 | static struct 1567 | { 1568 | uint32 lastts; 1569 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_mtrender.cpp ./emu4crt/src/snes_faust/ppu_mtrender.cpp 1570 | --- ./mednafen/src/snes_faust/ppu_mtrender.cpp 2019-12-24 04:24:48.000000000 -0800 1571 | +++ ./emu4crt/src/snes_faust/ppu_mtrender.cpp 2020-01-01 14:57:23.375643000 -0800 1572 | @@ -23,6 +23,10 @@ 1573 | #include "ppu.h" 1574 | #include "ppu_mtrender.h" 1575 | 1576 | +// SLK 1577 | +// #include 1578 | +// SLK end 1579 | + 1580 | #include 1581 | #include 1582 | 1583 | @@ -45,6 +49,12 @@ 1584 | namespace PPU_MTRENDER 1585 | { 1586 | 1587 | +// SLK 1588 | +int prev_resolution_w; 1589 | +int prev_resolution_h; 1590 | +// SLK 1591 | + 1592 | + 1593 | PPU_S PPU; 1594 | 1595 | #include "ppu_render_common.inc" 1596 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_render_common.inc ./emu4crt/src/snes_faust/ppu_render_common.inc 1597 | --- ./mednafen/src/snes_faust/ppu_render_common.inc 2019-12-24 04:24:48.000000000 -0800 1598 | +++ ./emu4crt/src/snes_faust/ppu_render_common.inc 2020-01-01 14:48:50.555151000 -0800 1599 | @@ -1621,6 +1621,16 @@ 1600 | T* const out_target = es->surface->pix() + out_line * es->surface->pitchinpix; 1601 | const uint32 w = ((BGMode & 0x7) == 0x5 || (BGMode & 0x7) == 0x6 || (ScreenMode & 0x08)) ? 512 : 256; 1602 | 1603 | +// SLK 1604 | + if(w != prev_resolution_w) 1605 | + { 1606 | + resolution_to_change_w = w; 1607 | + prev_resolution_w = w; 1608 | + resolution_to_change = true; 1609 | + } 1610 | +// SLK - end 1611 | + 1612 | + 1613 | es->LineWidths[out_line] = w; 1614 | // 1615 | LineTarget++; 1616 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/ppu_st.cpp ./emu4crt/src/snes_faust/ppu_st.cpp 1617 | --- ./mednafen/src/snes_faust/ppu_st.cpp 2019-12-24 04:24:48.000000000 -0800 1618 | +++ ./emu4crt/src/snes_faust/ppu_st.cpp 2020-01-01 14:56:43.112533000 -0800 1619 | @@ -34,6 +34,10 @@ 1620 | #include "input.h" 1621 | #include "cart.h" 1622 | 1623 | +// SLK 1624 | +#include 1625 | +// SLK end 1626 | + 1627 | #include 1628 | #include 1629 | 1630 | @@ -56,6 +60,11 @@ 1631 | namespace PPU_ST 1632 | { 1633 | 1634 | +// SLK 1635 | +int prev_resolution_w; 1636 | +int prev_resolution_h; 1637 | +// SLK 1638 | + 1639 | struct PPU_S 1640 | { 1641 | uint32 lastts; 1642 | diff -Naur -r --no-dereference ./mednafen/src/snes_faust/snes.cpp ./emu4crt/src/snes_faust/snes.cpp 1643 | --- ./mednafen/src/snes_faust/snes.cpp 2019-12-24 04:24:48.000000000 -0800 1644 | +++ ./emu4crt/src/snes_faust/snes.cpp 2020-01-01 14:50:31.525517000 -0800 1645 | @@ -43,6 +43,7 @@ 1646 | static MemoryStream* SpecExSS = NULL; 1647 | static int32 SpecExAudioExpected; 1648 | 1649 | + 1650 | struct ReadPatchInfoStruct 1651 | { 1652 | bool operator<(const ReadPatchInfoStruct& o) const 1653 | @@ -604,6 +605,8 @@ 1654 | } 1655 | } 1656 | 1657 | + 1658 | + 1659 | DMA_Init(); 1660 | // 1661 | // 1662 | @@ -617,6 +620,9 @@ 1663 | const unsigned region = MDFN_GetSettingUI("snes_faust.region"); 1664 | bool IsPAL, IsPALPPUBit; 1665 | 1666 | + 1667 | + 1668 | + 1669 | if(snsf_loader) 1670 | { 1671 | uint8* const cart_ram = CART_GetRAMPointer(); 1672 | @@ -671,6 +677,23 @@ 1673 | } 1674 | // 1675 | // 1676 | + 1677 | +// SLK - init. dynamic display video resolution - progressive by default 1678 | + printf("SNES FAUST snes - Regional mode: %s \n",(IsPAL ? "PAL" : "NTSC")); 1679 | + if(IsPAL) 1680 | + { 1681 | + resolution_to_change_h = 288; 1682 | + } 1683 | + else 1684 | + { 1685 | + printf(" Video mode set to 256 x 240\n"); 1686 | + resolution_to_change_h = 240; 1687 | + } 1688 | + resolution_to_change_w = 256; 1689 | + resolution_to_change = true; 1690 | + // SLK - end 1691 | + 1692 | + 1693 | INPUT_Init(); 1694 | { 1695 | const bool mte[2] = { MDFN_GetSettingB("snes_faust.input.sport1.multitap"), MDFN_GetSettingB("snes_faust.input.sport2.multitap") }; 1696 | diff -Naur -r --no-dereference ./mednafen/src/ss/vdp2_render.cpp ./emu4crt/src/ss/vdp2_render.cpp 1697 | --- ./mednafen/src/ss/vdp2_render.cpp 2019-12-24 04:24:48.000000000 -0800 1698 | +++ ./emu4crt/src/ss/vdp2_render.cpp 2019-12-26 07:31:34.355158000 -0800 1699 | @@ -145,6 +145,14 @@ 1700 | static uint8 LineColorCCRatio; 1701 | static uint8 BackCCRatio; 1702 | 1703 | +//SLK 1704 | +static uint8 prev_InterlaceMode = 0; 1705 | +static uint8 prev_HRes = 0; 1706 | +static uint8 prev_VRes = 0; 1707 | +static bool prev_BorderMode = 0; 1708 | +// SLK end 1709 | + 1710 | + 1711 | // 1712 | static struct 1713 | { 1714 | @@ -550,6 +558,39 @@ 1715 | InterlaceMode = (V >> 6) & 0x3; 1716 | VRes = (V >> 4) & 0x3; 1717 | HRes = (V >> 0) & 0x7; 1718 | + // SLK 1719 | + if(InterlaceMode != prev_InterlaceMode || HRes != prev_HRes) 1720 | + { 1721 | + printf("VDP2 Render - Television mode changed: %d\n",V); 1722 | + printf(" BorderMode: %d\n",BorderMode); 1723 | + printf(" PAL: %d\n",PAL); 1724 | + printf(" InterlaceMode: %d\n",InterlaceMode); 1725 | + printf(" VRes: %d\n",VRes); 1726 | + printf(" HRes: %d\n",HRes); 1727 | + prev_BorderMode = BorderMode; 1728 | + prev_InterlaceMode = InterlaceMode; 1729 | + prev_VRes = VRes; 1730 | + prev_HRes = HRes; 1731 | + // HRES 1732 | + switch(HRes){ 1733 | + case 0: 1734 | + resolution_to_change_w = 320; 1735 | + break; 1736 | + case 1: 1737 | + resolution_to_change_w = 352; 1738 | + break; 1739 | + case 2: 1740 | + resolution_to_change_w = 640; 1741 | + break; 1742 | + case 3: 1743 | + resolution_to_change_w = 704; 1744 | + break; 1745 | + } 1746 | + if(InterlaceMode >= 2){resolution_to_change_h = PAL ? 576 : 480;} else {resolution_to_change_h = PAL ? 288 : 240;} 1747 | + printf("SS - VDP2 Render - TV mode set to %dx%d",resolution_to_change_w,resolution_to_change_h); 1748 | + resolution_to_change = true; // Flag for video resolution change by VIDEO.cpp/MAIN.cpp 1749 | + } 1750 | + // SLK - end 1751 | break; 1752 | 1753 | case 0x02: 1754 | @@ -3295,12 +3336,20 @@ 1755 | { 1756 | gi->nominal_width = (ShowHOverscan ? 365 : 354); 1757 | gi->fb_height = 576; 1758 | + resolution_to_change_h = 288; // SLK - init crt mode 1759 | } 1760 | else 1761 | { 1762 | gi->nominal_width = (ShowHOverscan ? 302 : 292); 1763 | gi->fb_height = 480; 1764 | + resolution_to_change_h = 240; // SLK - init crt mode 1765 | } 1766 | + // SLK 1767 | + resolution_to_change_w = 320; 1768 | + resolution_to_change = true; // SLK - init crt mode 1769 | + // SLK - end 1770 | + 1771 | + 1772 | gi->nominal_height = LineVisLast + 1 - LineVisFirst; 1773 | 1774 | gi->lcm_width = (ShowHOverscan? 10560 : 10240); 1775 | diff -Naur -r --no-dereference ./mednafen/src/state.cpp ./emu4crt/src/state.cpp 1776 | --- ./mednafen/src/state.cpp 2019-12-24 04:24:48.000000000 -0800 1777 | +++ ./emu4crt/src/state.cpp 2019-12-26 07:31:35.795145000 -0800 1778 | @@ -470,6 +470,14 @@ 1779 | neowidth = MDFNGameInfo->nominal_width; 1780 | neoheight = MDFNGameInfo->nominal_height; 1781 | 1782 | + // SLK - Approximation to prevent SaveState snapshot corruption 1783 | + if(use_super_resolution) 1784 | + { 1785 | + neowidth = resolution_to_change_w; 1786 | + neoheight = DisplayRect->h; 1787 | + } 1788 | + // SLK - end 1789 | + 1790 | if(LineWidths[0] != ~0) 1791 | { 1792 | int32 first_w = LineWidths[DisplayRect->y]; 1793 | @@ -857,7 +865,9 @@ 1794 | MDFN_Error* me = dynamic_cast(&e); 1795 | 1796 | if(!fname && !suffix) 1797 | - MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1798 | + // SLK 1799 | + // MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); 1800 | + MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d not found."), CurrentState); // SLK - shorten message to fit low-res rendering 1801 | else 1802 | { 1803 | // FIXME: Autosave kludgery, refactor interfaces in the future to make cleaner. 1804 | -------------------------------------------------------------------------------- /resolutions/emu4crt_RESOLUTIONS_NATIVE.txt: -------------------------------------------------------------------------------- 1 | 640 x 240 @ 60.000000 NTSCp 2 | 512 x 240 @ 60.000000 NTSCp 3 | 368 x 240 @ 60.000000 NTSCp 4 | 320 x 240 @ 60.000000 NTSCp 5 | 256 x 240 @ 60.000000 NTSCp 6 | 7 | 640 x 480 @ 60.000000 NTSCi 8 | 512 x 480 @ 60.000000 NTSCi 9 | 368 x 480 @ 60.000000 NTSCi 10 | 320 x 480 @ 60.000000 NTSCi 11 | 256 x 480 @ 60.000000 NTSCi 12 | 13 | 640 x 288 @ 50.000000 PALp 14 | 512 x 288 @ 50.000000 PALp 15 | 368 x 288 @ 50.000000 PALp 16 | 320 x 288 @ 50.000000 PALp 17 | 256 x 288 @ 50.000000 PALp 18 | 19 | 640 x 576 @ 50.000000 PALi 20 | 512 x 576 @ 50.000000 PALi 21 | 368 x 576 @ 50.000000 PALi 22 | 320 x 576 @ 50.000000 PALi 23 | 256 x 576 @ 50.000000 PALi 24 | 25 | 352 x 240 @ 60.000000 SaturnNTSCp 26 | 704 x 240 @ 60.000000 SaturnNTSCp 27 | 28 | 352 x 480 @ 60.000000 SaturnNTSCi 29 | 704 x 480 @ 60.000000 SaturnNTSCi 30 | 31 | 352 x 288 @ 50.000000 SaturnPALp 32 | 704 x 288 @ 50.000000 SaturnPALp 33 | 34 | 352 x 576 @ 50.000000 SaturnPALi 35 | 704 x 576 @ 50.000000 SaturnPALi -------------------------------------------------------------------------------- /resolutions/emu4crt_RESOLUTIONS_SUPER.txt: -------------------------------------------------------------------------------- 1 | 2560 x 240 @ 60.000000 NTSCp 2 | 2560 x 480 @ 60.000000 NTSCi 3 | 2560 x 288 @ 50.000000 PALp 4 | 2560 x 576 @ 50.000000 PALi --------------------------------------------------------------------------------