diff --git a/readme.txt b/readme.txt index 214c6e9..9fe979d 100644 --- a/readme.txt +++ b/readme.txt @@ -1,1193 +1,1211 @@ -Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ - - - Visual Boy Advance GX - - https://github.com/dborth/vbagx - (Under GPL License) - -Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ - -Visual Boy Advance GX is a modified port of VBA-M. -With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube. - --=[ Releases ]=- - -https://github.com/dborth/vbagx/releases - --=[ Features ]=- - -* Wiimote, Nunchuk, Classic, and Gamecube controller support -* Rotation sensors, Solar sensors, and Rumble support -* Optional special Wii controls built-in for some games -* SRAM and State saving -* IPS/UPS patch support -* Custom controller configurations -* SD, USB, DVD, SMB, Zip, and 7z support -* Compatibility based on VBA-M r1231 -* MEM2 ROM Storage for fast access -* Auto frame skip (optional) for those core heavy games -* Turbo speed, video zooming, widescreen, and unfiltered video options -* Native loading/saving of ROMS and SRAM from Goomba (a GB emulator for GBA) -* Improved video rendering from RetroArch -* Screenshots can be displayed on the main menu -* Fixed pixel ratio mode (1x, 2x, and 3x) -* Borders (from Super Game Boy games or custom from .png) -* Wii U Pro Controller support -* 240p support - -Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0OΧψo· UPDATE HISTORY ·oψΧO0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' - -[2.3.7 - August 28, 2018] - -* Allow loader to pass two arguments instead of three (libertyernie) -* don't reset settings when going back to an older version -* Fix a few potential crashes caused by the GUI -* Other minor fixes/improvements -* Compiled with latest libOGC/devkitPPC - -[2.3.6 - December 11, 2016] - -* Restored Wiiflow mode plugin by fix94 -* Restored fix filebrowser window overlapping -* Change all files End Of Line to windows mode -* Remove update check for updates - -[2.3.5 - December 10, 2016] - -* Hide saving dialog that pops up briefly when returning from a game - -[2.3.4 - September 15, 2016] - -* Added the delete save file (SRAM / Snapshot) option -* Changed the box colors for the SRAM and Snapshots files to match the color - scheme of the emu GUI -* Change the "Power off Wii" exit option to completely turn off the wii, - ignoring the WC24 settings -* Updated settings file name in order to have it's own settings file name -* Added an option to switch between screenshots, covers, or artwork images, - with their respective named folders at the device's root. You can set which - one to show, by going to Settings > Menu > Preview Image. The .PNG image file - needs to have the same name as the ROM (e.g.: Mother 3.png) -* Removed sound from GUI (thanks to Askot) -* Added option to switch between the Green or Monochrome GB color screen. You - can set which one to show by going to Settings > Emulation > GB Screen Palette - -[2.3.3 - June 25, 2016] - -* Fixed the GC pad Down input on the File browser window -* Added Koston's green gb color screen -* Added the Screenshot Button -* Increased and Centered the Screenshot image and reduce game list width -* Added a background for the preview image -* Added the WiiuPro Controller icon on the controller settings -* Fix DSI error / Bug from Emulator Main Menu - -[2.3.2 - March 4, 2015] - libertyernie - -* Wii U: if widescreen is enabled in the Wii U setting, VBA GX will use a 16:9 - aspect ratio, except while playing a game with fixed pixel mode turned on -* There are now three options for border in the emulation settings menu (see - "Super Game Boy borders" section for details) - * PNG borders now supported for GBA games -* Video mode "PAL (50Hz)" renamed to "PAL (576i)" -* Video mode "PAL (60Hz)" renamed to "European RGB (480i)" -* 240p support added (NTSC and European RGB modes) -* All video modes now use a width of 704 for the best pixel aspect ratio - -[2.3.1b - November 8, 2014] - Glitch - -* Added FIX94's libwupc for WiiU Pro Controllers -* Added tueidj's vWii Widescreen Fix - -[2.3.1 - October 14, 2014] - libertyernie - -* Super Game Boy border support - * Borders can be loaded from (and are automatically saved to) PNG files - * Any border loaded from the game itself will override the custom PNG border -* Custom palette support from 2.2.8 restored -* Option added to select Game Boy hardware (GB/SGB/GBC/auto) -* Fixed pixel ratio mode added - * Overrides zoom and aspect ratio settings - * To squish the picture so it appears correctly on a 16:9 TV, you can open - the settings.xml file and add 10 to the gbFixed/gbaFixed value. However, - setting your TV to 4:3 mode will yield a better picture. -* Real-time clock fixes for GB/GBC games, including Pokιmon G/S/C - * RTC data in save file stored as little-endian - * Option added for UTC offset in the main menu (only required if you use the - same SRAM on other, time-zone-aware platforms) -* New option for selecting "sharp" or "soft" filtering settings - * "Sharp" was the default for 480p, "soft" was the default for 480i - -[2.3.0 - September 10, 2014] - libertyernie - -* VBA-M core updated to r1231 -* Tiled rendering used for GBA games (new VBA-M feature, originally from - RetroArch) - provides a major speed boost! -* Changes from cebolleto's version - * Screenshots can be displayed for each game on the menu - * Nicer 7-Zip support - * When you leave a folder, the folder you just left will be selected -* New options available: - * Disable the " Auto" string being appended to save files - * Disable frameskip entirely on GBA -* Keyboard fixed (from libwiigui r56) -* GUI prompt is now purple instead of green (button colors more intuitive) -* Goomba and Goomba Color ROM support: - * Any Game Boy ROM stored within a Goomba ROM can be loaded "natively" in - the Game Boy (Color) emulator (or the Goomba ROM can be loaded as GBA) - * Game Boy SRAM stored within Goomba SRAM is loaded and saved correctly - -[2.2.8 - July 29, 2012] - -* Fixed lag with GameCube controllers - -[2.2.7 - July 7, 2012] - -* Fixed PAL support - -[2.2.6 - July 6, 2012] - -* Support for newer Wiimotes -* Fixed missing audio channel bug (eg: in Mario & Luigi: Superstar Saga) -* Improved controller behavior - allow two directions to be pressed simultaneously -* Compiled with devkitPPC r26 and libogc 1.8.11 - -[2.2.5 - May 15, 2011] - -* Added Turkish translation - -[2.2.4 - March 23, 2011] - -* Fixed browser regressions with stability and speed - -[2.2.3 - March 19, 2011] - -* Improved USB and controller compatibility (recompiled with latest libogc) -* Enabled SMB on GameCube (thanks Extrems!) -* Added Catalan translation -* Translation updates - -[2.2.2 - October 7, 2010] - -* Fixed "blank listing" issue for SMB -* Improved USB compatibility and speed -* Added Portuguese and Brazilian Portuguese translations -* Channel updated (improved USB compatibility) -* Other minor changes - -[2.2.1 - August 14, 2010] - -* IOS 202 support removed -* USB 2.0 support via IOS 58 added - requires that IOS58 be pre-installed -* DVD support via AHBPROT - requires latest HBC - -[2.2.0 - July 22, 2010] - -* Fixed broken auto-update - -[2.1.9 - July 20, 2010] - -* Reverted USB2 changes - -[2.1.8 - July 14, 2010] - -* Ability to use both USB ports (requires updated IOS 202 - WARNING: older - versions of IOS 202 are NO LONGER supported) -* Hide non-ROM files -* Other minor improvements - -[2.1.7 - June 20, 2010] - -* USB improvements -* GameCube improvements - audio, SD Gecko, show thumbnails for saves -* Other minor changes - -[2.1.6 - May 19, 2010] - -* DVD support fixed -* Fixed some potential hangs when returning to menu -* Video/audio code changes -* Fixed scrolling text bug -* Other minor changes - -[2.1.5 - April 9, 2010] - -* Fix auto-save bug - -[2.1.4 - April 9, 2010] - -* Fixed issue with saves (GBA) and snapshots (GB) -* Most 3rd party controllers should work now (you're welcome!) -* Translation updates (German and Dutch) -* Other minor changes - -[2.1.3 - March 30, 2010] - -* Fixed ROM allocation. Should solve some unexplained crashes -* Numerous performance optimizations (thanks dancinninja!) -* DVD / USB 2.0 support via IOS 202. DVDx support has been dropped. It is - highly recommended to install IOS 202 via the included installer -* Multi-language support (only French translation is fully complete) -* Thank you to everyone who submitted translations -* SMB improvements/bug fixes -* Minor video & input performance optimizations -* Disabling rumble now also disables in-game rumbling -* Fixed saving of GB screen position adjustment - -[2.1.2 - December 23, 2009] - -* Numerous core optimizations (thanks dancinninjac!) -* File browser now scrolls down to the last game when returning to browser -* Auto update for those using USB now works -* Fixed scrollbar up/down buttons -* Minor optimizations - -[2.1.1 - December 7, 2009] - -* Save state corruption issues fixed - -[2.1.0 - December 2, 2009] - -* Fixed SMB (for real this time!) - -[2.0.9 - November 30, 2009] - -* Fixed SMB -* Added separate horizontal/vertical zoom options, and separate GB/GBA ones -* Improved scrolling timing - the more you scroll, the fast it goes -* Fixed reset button on Wii console - now you can reset multiple times -* APU optimization (dancinninjac) -* Minor code optimizations -* Reduce memory fragmentation - fixes out of memory crashes - -[2.0.8 - October 7, 2009] - -* Revamped filebrowser and file I/O -* Fixed MBC2 saving/loading -* Fixed some GB-Z80 instructions -* DVD loading in GameCube should work now (untested and unsupported) -* Many, many other bug fixes - -[2.0.7 - September 16, 2009] - -* Text rendering corrections -* SMB improvements -* Built with latest libraries -* Video mode switching now works properly -* Other minor bugfixes and cleanup - -[2.0.6 - July 22, 2009] - -* Fixed "No game saves found." message when there are actually saves. -* Fixed shift key on keyboard -* Text scrolling works again -* Change default prompt window selection to "Cancel" button - -[2.0.5 - July 9, 2009] - -* Faster SMB/USB browsing -* Last browsed folder is now remembered -* Fixed controller mapping reset button -* Fixed no sound on GameCube version -* Directory names are no longer altered -* Preferences now only saved on exit -* Fixed on-screen keyboard glitches -* SRAM auto-saved on power-off from within a game -* Prevent 7z lockups, better 7z error messages - -[2.0.4 - June 30, 2009] - -* Fixed auto-update -* Increased file browser listing to 10 entries, decreased font size -* Added text scrolling on file browser -* Added reset button for controller mappings -* Settings are now loaded from USB when loading the app from USB on HBC -* Fixed menu crashes caused by ogg player bugs -* Fixed memory card saving verification bug -* Fixed game savebrowser bugs -* Miscellaneous code cleanup/corrections - -[2.0.3 - May 30, 2009] - -* Fixed SD/USB corruption bug -* SMB works again -* GUI bugs fixed, GUI behavioral improvements -* GB Palette editing -* More built-in palettes -* Palettes now fade to white correctly instead of getting brighter -* Can now turn off palette colorizing -* Workaround for palette issue on Mega Man I GB - palette disabled -* Star Wars, TMNT, Lord Of The Rings, Castlevania Wii Controls -* Fix for WarioWare startup - Nunchuk C button or Wii Remote B button will now - make calibration easy by locking the gyroscope. -* Fixed issues with constant rumbling - -[2.0.2 - May 26, 2009] - -* Improved stability -* Fixed broken SDHC from HBC 1.0.2 update -* Fixed issues with returning to menu from in-game -* Add option to disable rumble -* Auto-determines if HBC is present - returns to Wii menu otherwise -* Unfiltered mode fixed -* Miscellaneous bugfixes - -[2.0.1 - April 30, 2009] - -* Multiple state saves now working -* Built with more stable libogc/libfat -* Fixed settings saving glitches -* Fixed Mortal Kombat GameCube controller bug -* Fixed Zelda DX palette bug -* Fixed Harry Potter 1-3 keyboard bug - -[2.0.0 - April 27, 2009] - -* New GX-based menu, with a completely redesigned layout. Has Wiimote IR - support, sounds, graphics, animation effects, and more -* Thanks to the3seashells for designing some top-notch artwork, to - Peter de Man for composing the music, and a special thanks to shagkur for - fixing libogc bugs that would have otherwise prevented the release -* Onscreen keyboard for changing save/load folders and network settings -* Menu configuration options (configurable exit button, wiimote orientation, - volumes) -* New save manager, allowing multiple saves and save browsing. Shows - screenshots for Snapshot saves, and save dates/times -* Added video shifting option -* Added video mode selection (recommended to leave on Automatic) -* USB Mouse support (buttons only) -* Keyboard shift key bug fixed -* Built-in 14 colour palettes for some monochrome gameboy games (Magnetic - Soccer, Malibu Beach Volleyball, Marble Madness, Metroid 2, Mortal Kombat, - Mortal Kombat II, Mortal Kombat 3, Mr. Do!) -* Rumble works in GBC games designed for rumble cartridges but shipped - without rumble cartridges, such as Disney's Tarzan for GBC -* Improved Mortal Kombat Wii Controls -* Mortal Kombat games now have many extra characters to choose -* Wii Controls for more Teenage Mutant Ninja Turtles games -* Improved Lego Star Wars controls -* Boktai menu now tells you when there can't be sun because it is night -* Minor bug fixes - -[1.0.9 - April 7, 2009] - -* Gamecube controller should no longer rumble constantly - -[1.0.8 - April 4, 2009] - -* "Match Wii Game" controls option! Games that have a Wii equivalent can be - played using the controls for that Wii game. For example all Zelda games - can be played with Twilight Princess controls. See the Instructions section - below for important details. -* Rotation/Tilt sensor games all work -* Solar sensors (Boktai 1/2/3) -* Rumble (except for games that rely on Gameboy Player) -* Keyboard -* PAL support, finally! -* New scaling options, choose how much stretching you want -* Colourised games now partially work but still have distortion -* "Corvette" no longer has a screwed up palette (but still crashes) -* Triggers net reconnection on SMB failure -* Source code refactored, and project file added -* Instructions section added to this readme file - -[1.0.7 - January 27, 2009] - -* Updated to VBA-M r847 -* Corrected sound interpolation -* Faster SD/USB - new read-ahead cache -* Removed trigger of back to menu for Classic Controller right joystick -* Fixed a bug with reading files < 2048 bytes -* Fixed GBA games on GameCube -* Fixed homebrew GBA games on GameCube -* Fixed some memory leaks, buffer overflows, etc -* Code cleanup, other general bugfixes - -[1.0.6 - December 24, 2008] - -* Fixed save state saving bug -* Fixed unstable SD card access -* Proper SD/USB hotswap (Wii only) -* Auto-update feature (Wii only) -* Rewritten SMB access - speed boost, NTLM now supported (Wii only) -* Improved file access code -* Resetting preferences now resets controls -* Minor bug fixes - -[1.0.5 - November 19, 2008] - -* SDHC works now -* Frameskipping tweaks -* Fixed snapshot loading issue -* Full widescreen support -* Changed scaling -* Zooming fixed (thanks eke-eke!) -* PAL timing changes - EURGB60 mode forced -* Wii - Added console/remote power button support -* Wii - Added reset button support (resets game) -* Wii - Settings file is now named settings.xml and is stored in the same - folder as the DOL (eg: apps/vbagx/settings.xml) -* GameCube - Added DVD motor off option -* GameCube - Fixed GBA loading issue - -[1.0.4 - October 28, 2008] - -* Complete port of VBA-M - now uses blaarg's new audio core, latest GB core -* Frameskipping improvements -* Sound processing improved - L-R channel reversal corrected, skipping fixed -* Saving problems fixed, game compatibility improved -* IPS/UPS/PPF patch support -* SD/USB hot-swapping! -* SDHC support -* Zoom setting saved -* Widescreen correction option -* GameCube support is back, including Qoob support! - -[1.0.3 - October 15, 2008] - -* New timing / frameskip algorithm - should (hopefully) work 100% better! -* Performance improvements - video threading, PPC core partly activated -* Video zooming option -* Unfiltered video option -* 7z support -* Loading progress bars added - -[1.0.2 - October 6, 2008] - -* New core! The core is now a custom combination of VBA-M and VBA 1.72 -* Added DVD, SMB, ZIP, GameCube MC support -* Faster USB/SD speeds -* Screen alignment and flickering problems fixed -* 128K save support added -* Better emulation speeds. Should now be nearly full speed all the time - for most games. -* Turbo speed feature. Mapped to right C-stick (classic controller & - Gamecube controller), and A+B for wiimote -* Controller mapping preferences bug fixed. Your preferences will reset - automatically to correct any problems in your preferences file -* Many other tweaks behind the scenes - -[1.0.1 - September 18, 2008] - -* GBA games now run at full speed -* Menu improvements, with spiffy new background -* Fixed L/R buttons - they work now - -[1.0.0 - September 16, 2008] - -* Now compiles with devkitpro r15 -* One makefile to make all versions -* Complete rewrite based on code from SNES9x GX -* Now has a menu! ROM selector, preferences, controller mapping, etc -* Wiimote, Nunchuk, and Classic controller support -* Button mapping for all controller types -* Full support for SD and USB -* Load/save preference selector. ROMs, saves, and preferences are - saved/loaded according to these -* 'Auto' settings for save/load - attempts to automatically determine - your load/save device(s) - SD, USB -* Preferences are loaded and saved in XML format. You can open - VBAGX.xml edit all settings, including some not available within - the program - -Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0OΧψo· SETUP & INSTALLATION ·oψΧO0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' - -Unzip the archive. You will find the following folders inside: - -apps Contains Homebrew Channel ready files - (see Homebrew Channel instructions below) - -vbagx Contains the directory structure required for storing - roms and saves. By default, roms are loaded from - "vbagx/roms/" and saves / preferences are stored in - "vbagx/saves/". - --=[ Loading / Running the Emulator ]=- - -Wii - Via Homebrew Channel: --------------------------------- -The most popular method of running homebrew on the Wii is through the Homebrew -Channel. If you already have the channel installed, just copy over the apps folder -included in the archive into the root of your SD card. - -Remember to also create the vbagx directory structure required. See above. - -If you haven't installed the Homebrew Channel yet, read about how to here: -http://hbc.hackmii.com/ - -Gamecube: --------------------------------- -You can load VBAGX via sdload and an SD card in slot A, or by streaming -it to your Gamecube, or by booting a bootable DVD with VBAGX on it. -This document doesn't cover how to do any of that. - -Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0OΧψo· INSTRUCTIONS ·oψΧO0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' -If you have upgraded from a previous version, the emulator may start with a -message that your preferences have been reset. You will need to set your -preferences how you want them. - -Otherwise the emulator will start at the main menu, which is a list of game -ROMs. There is also a settings button to choose how and where to load or -save files, and to change menu settings. - -Navigate the menu with the D-Pad, or the Wiimote pointer, and select options -with the A button. Press the B button to swap between controlling a list box -and controlling the buttons. Pressing the Home button will exit from the -main menu. You can choose what exiting will do by using the settings menu. - -Click on the logo to see the credits. - -When choosing a file, use left and right to go up or down a page. - -Once you choose a game, the game will start. But you can get back to a menu -by pressing Home. This takes you to the in-game menu, where you can save, -load, reset, or change settings. The settings apply to all games, not just -the current one. These settings are different from the settings on the main -menu. If you are playing a Boktai game with a solar sensor, there will also -be a fifth button which lets you change the weather. The sunlight is based -on the weather, the time of day, and the angle of your Wiimote. - -Saving and loading let you choose two kinds of save files. SRAM is the -normal kind of saving and loading that you have on a real gameboy. It only -saves up to the last checkpoint or savepoint in the game. Or you can save -a better way by using the emulator's special "Snapshot" feature which -saves the state of everything, exactly where you are up to. Loading a -Snapshot may erase your "SRAM (Auto)" so be careful. - -From the game menu you can return to the game by pressing Home again, or by -clicking on the "Close" button in the top right. Or to quit that game and -choose a different game, click on the "Main Menu" button. - -If you don't want to load ROMs from the SD card, you can go to the -settings menu and choose where to load from. You can load from SD cards, -USB memory sticks/hard drives, DVD (if you installed DVDX), gamecube memory -cards, or from shared folders over the network (this is called SMB). - -ROMs can be in ZIP files, but the ROM must be the first file in the ZIP. If -not, you will get an error. ROMs can also be in .7z files, or ordinary rom -files. - -Patches can be used to colourise a monochrome gameboy game, or to translate -a game into your language, or to stop the game from needing special hardware. -Search the internet for patches. Many games have been translated by fans. -They can be in IPS or UPS format. You don't need to patch anything yourself. -Just put the IPS or UPS file in the vbagx/roms folder along with the rom -itself. The patch must have the same name as the rom. Patches can not be put -inside the ZIP file. If a rom is zipped, you might need to check inside the -zip for the actual rom filename. - -Colourised games still have some distortion in this version, but it is -improved from the previous version, and better than VBA-M. Some unpatched -monochrome gameboy games have built-in palettes in this emulator and will -appear in colour. - -You must not use patched versions of Boktai roms! (Except for the translation -patch for Boktai 3, which is highly recommended). The patches are for old -emulators that don't support the solar sensor. VBA GX and NO$GBA support the -solar sensor natively, and the patch will stop them from working. - -You must also not use patched versions of WarioWare Twisted, Kirby's Tilt n -Tumble, or Yoshi's Universal Gravitation (Topsy Turvy). The original roms -are fully supported, and the patch will stop them from working. - --=[ Controls ]=- - -See the website at http://www.wiibrew.org/wiki/VBA for better control -documentation, with illustrations and tables. - -The default controls are... - -+ = Gameboy Start Button -- = Gameboy Select Button -Home = Show emulator's game menu - -Wii Remote by itself: -Hold the Wii Remote sideways. -2 = Gameboy A Button -1 = Gameboy B Button -A = Gameboy R Button -B = Gameboy L Button - -Wii Remote + Nunchuk: -Hold the Nunchuk and ignore the Wii Remote. -Z = Gameboy A Button -C = Gameboy B Button - -Classic Controller: -B = Gameboy A Button -Y = Gameboy B Button -R = Gameboy R Button -L = Gameboy L Button - -You can configure the controls how you want from the controls menu. Different -controls will be used depending on what you have plugged into the Wii Remote. -Nunchuk means Nunchuk + Wii Remote. Gamecube controllers can -be used at the same time as Wii Remotes and all control the same player. -When configuring controls, press HOME to cancel. - -But the controls you choose will be overridden for certain games if you -choose "Match Wii Game" (or "Match Gamecube Game" on a Gamecube) and you have -the appropriate expansion plugged in. If the game does not have special Wii -controls, then the controls you chose will be used. - -Gameboy and Gameboy colour games don't have L and R buttons. Those buttons -only work in Gameboy Advance games. - -In addition to the controls you can configure, these other controls apply: - -HOME, Escape: returns you to the emulator's game menu. Then press B to go -to the main menu and B again to return to the game. -A+B, Spacebar, or right analog stick: fast forward -Right analog stick: zoom (if enabled) - --=[ Super Game Boy borders ]=- - -VBA-GX has supported Super Game Boy borders since 2.3.1. You can enable this -feature in the Emulation settings on the main menu. - -Borders can be loaded from two locations: -* PNG files in the borders folder (by default, /vbagx/borders) -* The game itself - -Borders will only be loaded from the game itself when the emulator is running -in Super Game Boy mode, and the border setting in Emulation settings is set to -"From game (SGB only)". (You can also use the Emulation settings menu to -force SGB mode even for Game Boy Color games.) If the borders folder exists, -but no border for the game is present, the loaded Super Game Boy border will -be written to a .png file, which can be loaded later in "From .png file" mode. - -In addition, if the borders folder exists but there is no border for the game, -the first border loaded from the game will be written to a PNG file so it can -be loaded in the future (even in Game Boy Color mode.) This means after you -run a game once in SGB mode, you can then use the same border in GBC mode. - -If the border setting is set to "From .png file", borders will be loaded -from the borders folder. Borders can be up to 640x480 and will work for both -Game Boy (Color) and Game Boy Advance games. - -For both loading and saving, the PNG filename is [TITLE].png, where [TITLE] -is the ROM title defined at 0x134 (for GB games) or 0xA0 (for GBA games). For -example, POKEMON_SFXAAXE.png will be loaded for Pokιmon Silver. If no PNG file -by that name exists, VBA-GX will try loading default.png (for GB games) or -defaultgba.png (for GBA games) instead. - -Since the borders are rendered along with the video output of the game, the -pixels in the border will be the same size as game pixels. This means that -a Game Boy game will appear in the middle 160x144 pixels of the border, and a -Game Boy Advance game will appear in the middle 240x160 pixels, regardless of -the resolution of the border PNG image. - --=[ Match Wii Controls ]=- - -Special Wii controls exist for the following games: - -These Zelda games can be played with Twilight Princess controls: -The Legend Of Zelda, Zelda 2, A Link To The Past, Link's Awakening (DX), -Oracle of Ages, Oracle of Seasons, Minish Cap - -These Mario games can be played with Mario Galaxy controls: -Super Mario Bros., Super Mario Bros. DX, Super Mario 2, Super Mario (2) -Advance, Super Mario 3, Super Mario World, Yoshi's Island, -Yoshi's Universal Gravitation (Topsy Turvy) - -Mario Kart can be (sort of) played with Mario Kart wii controls, but it -doesn't work very well. - -These Metroid games can be played with Metroid Prime 3 controls: -Metroid Zero Mission, Metroid 1, Metroid 2, Metroid Fusion - -These Mortal Kombat games can be played with Mortal Kombat Armageddon controls: -Mortal Kombat, Mortal Kombat II, Mortal Kombat 3, Mortal Kombat 4, Mortal -Kombat Advance, Mortal Kombat Deadly Alliance, Mortal Kombat Tournament -Edition - -These Lego games can be played with Lego Star Wars the Complete Saga -controls: -Lego Star Wars The Video Game, Lego Star Wars The Original Trilogy - -These Teenage Mutant Ninja Turtles games can be played with TMNT Wii controls: -TMNT, Teenage Mutant Ninja Turtles, Fall of the Foot Clan, Back from the Sewers, -Radical Rescue - -These Harry Potter games can be played with Harry Potter and the Order of -the Phoenix Wii controls: -Harry Potter 1, Harry Potter 1 GBC, Harry Potter 2, Harry Potter 2 GBC, -Harry Potter 3, Harry Potter 4, Harry Potter 5 - -These Medal Of Honour games can be played with Medal Of Honour Wii controls: -Medal Of Honour Underground, Medal Of Honour Infiltrator - -One Piece can be played with One Piece Unlimited Adventure controls. - -Boktai 1, Boktai 2, Boktai 3, and Kirby's Tilt n Tumble can be played with -controls designed for them. - --=[ Zelda, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Zelda games use the same controls as Twilight Princess on the Wii or -Gamecube. You can also connect a Classic Controller to use similar controls -to the Ocarina Of Time for the Virtual Console, but with the R trigger -acting as the B button and an inventory like Twilight Princess. With nothing -plugged in to the Wii Remote, your configured controls are used instead. - -The Wii Zelda controls are: -=========================== - -Swing your Wii Remote to draw or swing your sword. Press A to put your sword -away again. The 2 handed sword can't be drawn this way, and must be drawn -manually from the items menu, but you can swing it like normal. - -Shake your Nunchuk to do a spin attack. - -Use the Z Button to Z-Target and to draw and use your shield. While -Z-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for Z-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -pulling things, etc. It will also put away your sword or shield. In Zelda 2, -it will jump. - -Use the C Button to fast forward. It was originally the camera button in -Twilight Princess. - -Press the B Button to use the currently selected item. 3 other items will be -mapped to Left, Down, and Right D-Pad buttons. Swap the currently selected -item with one of those items by pressing that D-Pad button. The three slots -correspond to the first 3 slots in your inventory. In Minish Cap, the D-Pad -buttons use the item directly instead of swapping it with the B Button, and -the B Button is the same as the down button. In Minish Cap the left item is -always the Kinstones and the down and right items correspond to the B and A -slots. - -Up on the D-Pad talks to Midna, or to your hat. It will take you to the save -screen in Link's Awakening, or to the secondary items screen in the Oracle -games. - -The 1 Button goes to the Map screen. -The - Button goes to the Items screen. -The + Button goes to the Quest Status screen - -On the Items screen, choose an item and then press either the B Button or the -D-Pad button to move it to that slot. The change may not be visible until you -go to another screen and back. In Link's Awakening you can toggle Bomb -Arrows by choosing the bombs and pressing Z. It will rumble for a short time -when bomb arrows are deactivated, and for a long time when bomb arrows are -activated. You still need to equip the bow to use bomb arrows. In Minish Cap -you should be able to use the IR pointer function to select items. - -The Gamecube controller Zelda controls are: -=========================================== - -B is the sword button. Use it to draw or swing your sword. Hold B for a spin -attack. Press A to put the sword away again. The 2 handed sword can't be -drawn this way, and must be selected manually from the items screen, but can -be swung with this (or any other) button. - -Use the L Trigger to L-Target and to draw and use your shield. While -L-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for L-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -etc. It will also put away your sword or shield. In Zelda 2, it will jump. - -Use the R Trigger to pull on blocks or walls, or to lift things. You must -have a bracelet or gloves to lift some objects. The bracelet or gloves will -be equipped automatically. This feature is unique to the Gamecube controller. - -Use the right analog stick to fast forward. It was originally the camera -control in Twilight Princess. - -Press the X or Y buttons to use the two equipped items. These two items both -share the B slot, except in Minish Cap where one is in the A slot. The item -that was not used last will be in the first slot in your inventory. - -Right on the D-Pad takes you to the map. -Up on the D-Pad takes you to the items screen. -Start takes you to the quest status screen. - -The Z trigger talks to Midna, or to your hat. It will take you to the save -screen in Link's Awakening, or to the secondary items screen in the Oracle -games. - -The Classic controller Zelda controls are: -========================================== - -B is the sword button. Use it to draw or swing your sword. Hold B for a spin -attack. Press A to put the sword away again. The 2 handed sword can't be -drawn this way, and must be selected manually from the items screen, but can -be swung with this (or any other) button. - -Use the L Trigger to L-Target and to draw and use your shield. While -L-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for L-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -pulling, etc. It will also put away your sword or shield. In Zelda 2, it -will jump. - -Use the ZL Button to fast forward. - -Press the R Button to use the currently selected item. 3 other items will be -mapped to Left, Down, and Right on the right analog stick. They are also -mapped to ZR, Y, and X. Swap the currently selected item with one of those -items by pressing that button or direction. The three slots correspond to -the first 3 slots in your inventory. In Minish Cap, the D-Pad buttons use the -item directly instead of swapping it with the B Button, and the B Button is -the same as the down button. In Minish Cap the left item is always the -Kinstones and the down and right items correspond to the B and A slots. - -+ (Start) takes you to the subscreens. -- (Select) takes you to the map or changes subscreens. - -Up on the analog stick talks to Midna, or to your hat. - - --=[ Mario, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Mario or Yoshi games use the same controls as Super Mario Galaxy on the -Wii. You can also connect a Classic Controller to use similar controls to -Super Mario World on the SNES. - -The Wii Mario controls are: -=========================== - -Shake the Wii Remote to do a spin attack, or to shoot fireballs when you are -fire Mario. In some games that have a spin attack, you will need to use the -B Button instead to shoot fireballs. You can also dismount Yoshi by shaking. - -Walk by moving the joystick a little, run by moving the joystick a lot. - -A = jump -B = shoot, run, hold on to things, yoshi's tongue, etc. -Z = crouch or lay egg. Press Z while in the air to butt stomp. -C = camera. Hold C to look around with the joystick. -D-Pad = look around, or walk in some games -+ = pause -1 = throw egg if you are Yoshi - -The Classic Controller Mario controls are: -========================================== - -Walk by moving the joystick a little, run by moving the joystick a lot. - -B = jump -A = spin attack -X/Y = shoot, run, hold on to things, yoshi's tongue, etc. -ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp. -+ = pause -L/R = look around (if the game supports it) -ZR = fast forward (8-bit Game Boy only) - -In Super Mario World and Super Mario Land 2, you can use the A or R -buttons for a spin jump. - --=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The controls are the same as all other Mario or Yoshi games, except that -tilting the Wii Remote tilts the world and the screen. This affects -everything in the world and also how you move. - - --=[ Metroid, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Metroid games use the same controls as Metroid Prime 3: Corruption on -the Wii. You aim up and down by pointing the Wii Remote up and down. - -The Wii Metroid controls are: -============================= -Aim up and down by pointing the Wii Remote up and down. - -Flick the Wii remote up while in Morph Ball to spring jump. - -A = shoot -B = jump -Down on D-Pad = fire missile -C = toggle Morph Ball -- = start -+ = toggle super missiles -1 = map -2 = hint - - --=[ TMNT, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The TMNT games (except Battle Nexus) use the same controls as TMNT on Wii, -or GameCube. With a Classic Controller they use the same controls as on -the Playstation version. - -The Wii TMNT controls are: -========================== -Shake the Wii Remote to attack or to throw away a weapon if -in the air. Also shake to pick up a weapon. - -Shake the Nunchuk to do a spin kick. - -A = jump -B = swap turtle, or charge attack -B while pointing up = super family move -C = roll -Z = special move - --=[ Boktai, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The 3 Boktai games use special controls that I created. They are not based on -anything, since the real game uses a solar sensor. - -The controls are the same with or without a Nunchuk. - -The Wii Boktai controls are: -============================ - -Point your Wii Remote at the sky to quickly charge your Gun Del Sol. Point -your Wii Remote at the ground to block the sunlight and prevent it from -charging or overheating. Or hold it like normal to use it like normal. - -Press Home to set the real life weather in the emulator's game menu. Note -that if it is night time in real life, there will not be any sun, regardless -of what you set the weather to. Please set the weather honestly or it spoils -the fun. Note that maximum sun is not actually the best, since it rots fruit, -and overheats your gun. The weather must be set each time you play, it is not -saved. - -Swing your Wii Remote to swing your sword or other weapon, if you have one. - -D-Pad or Nunchuk joystick walks. - -Press B to fire your Gun Del Sol. - -A = read signs, open chests, talk to people -C or 2 = look around, or change subscreen (R) -+ = start -- = select -Z or 1 = change element, or change subscreen (L) -1 (if Nunchuk plugged in) = fast forward - --=[ WarioWare Twisted, Match Wii Controls ]=- - -NOTE: For unknown reasons (but probably related to the update of the VBA-M -emulator code), WarioWare Twisted will no longer work on VBA-GX. For now, you -will need to go back to VBA-GX 2.2.8 to play it. - --=[ Kirby's Tilt n Tumble, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -Kirby's Tilt n Tumble uses similar controls to the Gameboy game. - -The Kirby Tilt n Tumble controls are: -===================================== - -Tilt the Wii Remote to tilt the world. Shake the Wii Remote to flick Kirby -and the monsters up into the air. - -A = shoot yourself out of holes in the ground, or jump from clouds. - --=[ Mortal Kombat, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Mortal Kombat games use the same controls as Mortal Kombat Armaggedon -for the Wii, except that special moves gestures are not implemented yet. - -The Mortal Kombat Wii controls are: -=================================== - -Use the Nunchuk joystick to move and jump. - -D-Pad left = Low Punch -D-Pad up = High Punch -D-Pad down = Low Kick -D-Pad right = High Kick -Z = block -A = throw -C = change style, run, change costume or character -+ = pause -- = change costume or character - --=[ Lego Star Wars, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -Both Lego Star Wars games use the same controls as Lego Star Wars: The -Complete Saga for the Wii. - -The Lego Star Wars Wii controls are: -==================================== -Swing the Wii Remote to swing your lightsaber. -Flick the Wii Remote up to grapple. - -A = Jump -B = Shoot -Z = Use the force, build lego -C = Change characters, talk to people -- = force power, special ability -+ = start -1/2 = fast forward - --=[ Harry Potter, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All the Harry Potter games use the same controls as Harry Potter & The Order -Of The Phoenix on the Wii. Spell gestures are not supported yet. - -The Harry Potter Wii controls are: -================================== -Wave the Wii Remote to cast a spell. -Nunchuk joystick walks. -D-Pad changes subscreen in the map and navigates menu. -In Harry Potter and the Order of the Phoenix you must use the IR Pointer -to select where to cast a spell. - -A = Talk, open door, push button, interract, etc. / Jinx -B = Use your wand / charm / cancel -Z = run (fast forward) / sneak -C = show location name / flute / jump -- = Maurauders map / Tasks -+ = pause / menu -1/2 = change spells - --=[ Medal of Honour, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All the Medal of Honour games use the same controls as various -Medal of Honour games and modes on the Wii. - -The Medal of Honour Wii controls are: -===================================== - -In Medal of Honour Underground you turn by aiming with the Wii Remote IR -pointer on the screen like any FPS game. In Medal of Honour Infiltrator, -you don't. - -Swing the Wiimote up to reload. -Move with the Nunchuk joystick. - -B = shoot -- = use -+ = pause, objectives, menu -2 / D-Pad Up = reload -D-Pad Left/Right = change weapons -D-Pad Down = toggle crouch -C = strafe -1 = run - --=[ One Piece, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -One Piece uses the same controls as One Piece Unlimited Adventure on the Wii -or One Piece Grand Adventure (and others) on the Gamecube. - -The One Piece Wii controls are: -=============================== - -A = attack -B = jump -- = change character -+ = pause -C = dash (double click and hold) -Z = grab -2 = fast forward -1 = select (maybe does nothing) - -The One Piece Gamecube controls are: -=============================== - -A = attack -X = attack up -Y = jump -B = grab -R Trigger = change character -start = pause -L Trigger = dash (double click and hold) -Z = grab -right analog stick = fast forward -1 = select (maybe does nothing) - --=[ Kid Dracula, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -(There's no Kid Dracula game for the Wii, but this is a good opportunity to -show off some fancy memory-swapping tricks. -libertyernie) - -The Kid Dracula Wii controls (remote + nunchuk) are: -==================================================== - -A = jump -B = use selected weapon -Z = use NOR weapon (fireball) -C = use BAT weapon (turn into bat for 5 sec) -+ = pause -- = switch item -1/2 = fast forward - -The Kid Dracula Classic Controller controls are: -================================================ - -A/B = jump -Y = use selected weapon -X = use NOR weapon (fireball) -R/ZR = use BAT weapon (turn into bat for 5 sec) -+ = pause -- = switch item -1/2 = fast forward - -In Kid Dracula, pressing the "fire" button will always shoot a small fireball, -but holding the button for a second or so to charge up the shoot lets you use -whichever item is selected. - -Pressing B (nunchuk) or Y (classic) will switch back to whatever item was -selected before you pressed Z/C (nunchuk) or X/R/ZR (classic), unless you have -switched items since then. - -Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ - --=[ Credits ]=- - - Coding & menu design Tantric - Codebase update & Goomba libertyernie - Menu screenshots cebolleto - GBA tiled rendering bgK (for RetroArch) - Additional coding Carl Kenner, dancinninjac - Menu artwork the3seashells - Menu sound Peter de Man - - ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ - VBA GameCube/Wii SoftDev, emukidid - - Visual Boy Advance - M VBA-M Team - Visual Boy Advance Forgotten - libogc/devkitPPC shagkur & wintermute - FreeTypeGX Armin Tamzarian - - And many others who have contributed over the years! - -Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ - - VBAGX Web Site - https://github.com/dborth/vbagx - -Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ +Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ + + - Visual Boy Advance GX - + https://github.com/dborth/vbagx + (Under GPL License) + +Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ + +Visual Boy Advance GX is a modified port of VBA-M. +With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube. + +-=[ Releases ]=- + +https://github.com/dborth/vbagx/releases + +-=[ Features ]=- + +* Wiimote, Nunchuk, Classic, and Gamecube controller support +* Rotation sensors, Solar sensors, and Rumble support +* Optional special Wii controls built-in for some games +* SRAM and State saving +* IPS/UPS patch support +* Custom controller configurations +* SD, USB, DVD, SMB, Zip, and 7z support +* Compatibility based on VBA-M r1231 +* MEM2 ROM Storage for fast access +* Auto frame skip (optional) for those core heavy games +* Turbo speed, video zooming, widescreen, and unfiltered video options +* Native loading/saving of ROMS and SRAM from Goomba (a GB emulator for GBA) +* Improved video rendering from RetroArch +* Screenshots can be displayed on the main menu +* Fixed pixel ratio mode (1x, 2x, and 3x) +* Borders (from Super Game Boy games or custom from .png) +* Wii U Pro Controller support +* 240p support + +Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0OΧψo· UPDATE HISTORY ·oψΧO0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' + +[2.3.8] + +* Restored changes lost from 2.3.0 core upgrade (GameCube virtual memory, + optimizations from dancinninjac, GB color palettes, rotation/tilt for + WarioWare Twisted, in-game rumble) + +[2.3.7 - August 28, 2018] + +* Allow loader to pass two arguments instead of three (libertyernie) +* don't reset settings when going back to an older version +* Fix a few potential crashes caused by the GUI +* Other minor fixes/improvements +* Compiled with latest libOGC/devkitPPC + +[2.3.6 - December 11, 2016] + +* Restored Wiiflow mode plugin by fix94 +* Restored fix filebrowser window overlapping +* Change all files End Of Line to windows mode +* Remove update check for updates + +[2.3.5 - December 10, 2016] + +* Hide saving dialog that pops up briefly when returning from a game + +[2.3.4 - September 15, 2016] + +* Added the delete save file (SRAM / Snapshot) option +* Changed the box colors for the SRAM and Snapshots files to match the color + scheme of the emu GUI +* Change the "Power off Wii" exit option to completely turn off the wii, + ignoring the WC24 settings +* Updated settings file name in order to have it's own settings file name +* Added an option to switch between screenshots, covers, or artwork images, + with their respective named folders at the device's root. You can set which + one to show, by going to Settings > Menu > Preview Image. The .PNG image file + needs to have the same name as the ROM (e.g.: Mother 3.png) +* Removed sound from GUI (thanks to Askot) +* Added option to switch between the Green or Monochrome GB color screen. You + can set which one to show by going to Settings > Emulation > GB Screen Palette + +[2.3.3 - June 25, 2016] + +* Fixed the GC pad Down input on the File browser window +* Added Koston's green gb color screen +* Added the Screenshot Button +* Increased and Centered the Screenshot image and reduce game list width +* Added a background for the preview image +* Added the WiiuPro Controller icon on the controller settings +* Fix DSI error / Bug from Emulator Main Menu + +[2.3.2 - March 4, 2015] - libertyernie + +* Wii U: if widescreen is enabled in the Wii U setting, VBA GX will use a 16:9 + aspect ratio, except while playing a game with fixed pixel mode turned on +* There are now three options for border in the emulation settings menu (see + "Super Game Boy borders" section for details) + * PNG borders now supported for GBA games +* Video mode "PAL (50Hz)" renamed to "PAL (576i)" +* Video mode "PAL (60Hz)" renamed to "European RGB (480i)" +* 240p support added (NTSC and European RGB modes) +* All video modes now use a width of 704 for the best pixel aspect ratio + +[2.3.1b - November 8, 2014] - Glitch + +* Added FIX94's libwupc for WiiU Pro Controllers +* Added tueidj's vWii Widescreen Fix + +[2.3.1 - October 14, 2014] - libertyernie + +* Super Game Boy border support + * Borders can be loaded from (and are automatically saved to) PNG files + * Any border loaded from the game itself will override the custom PNG border +* Custom palette support from 2.2.8 restored +* Option added to select Game Boy hardware (GB/SGB/GBC/auto) +* Fixed pixel ratio mode added + * Overrides zoom and aspect ratio settings + * To squish the picture so it appears correctly on a 16:9 TV, you can open + the settings.xml file and add 10 to the gbFixed/gbaFixed value. However, + setting your TV to 4:3 mode will yield a better picture. +* Real-time clock fixes for GB/GBC games, including Pokιmon G/S/C + * RTC data in save file stored as little-endian + * Option added for UTC offset in the main menu (only required if you use the + same SRAM on other, time-zone-aware platforms) +* New option for selecting "sharp" or "soft" filtering settings + * "Sharp" was the default for 480p, "soft" was the default for 480i + +[2.3.0 - September 10, 2014] - libertyernie + +* VBA-M core updated to r1231 +* Tiled rendering used for GBA games (new VBA-M feature, originally from + RetroArch) - provides a major speed boost! +* Changes from cebolleto's version + * Screenshots can be displayed for each game on the menu + * Nicer 7-Zip support + * When you leave a folder, the folder you just left will be selected +* New options available: + * Disable the " Auto" string being appended to save files + * Disable frameskip entirely on GBA +* Keyboard fixed (from libwiigui r56) +* GUI prompt is now purple instead of green (button colors more intuitive) +* Goomba and Goomba Color ROM support: + * Any Game Boy ROM stored within a Goomba ROM can be loaded "natively" in + the Game Boy (Color) emulator (or the Goomba ROM can be loaded as GBA) + * Game Boy SRAM stored within Goomba SRAM is loaded and saved correctly + +[2.2.8 - July 29, 2012] + +* Fixed lag with GameCube controllers + +[2.2.7 - July 7, 2012] + +* Fixed PAL support + +[2.2.6 - July 6, 2012] + +* Support for newer Wiimotes +* Fixed missing audio channel bug (eg: in Mario & Luigi: Superstar Saga) +* Improved controller behavior - allow two directions to be pressed simultaneously +* Compiled with devkitPPC r26 and libogc 1.8.11 + +[2.2.5 - May 15, 2011] + +* Added Turkish translation + +[2.2.4 - March 23, 2011] + +* Fixed browser regressions with stability and speed + +[2.2.3 - March 19, 2011] + +* Improved USB and controller compatibility (recompiled with latest libogc) +* Enabled SMB on GameCube (thanks Extrems!) +* Added Catalan translation +* Translation updates + +[2.2.2 - October 7, 2010] + +* Fixed "blank listing" issue for SMB +* Improved USB compatibility and speed +* Added Portuguese and Brazilian Portuguese translations +* Channel updated (improved USB compatibility) +* Other minor changes + +[2.2.1 - August 14, 2010] + +* IOS 202 support removed +* USB 2.0 support via IOS 58 added - requires that IOS58 be pre-installed +* DVD support via AHBPROT - requires latest HBC + +[2.2.0 - July 22, 2010] + +* Fixed broken auto-update + +[2.1.9 - July 20, 2010] + +* Reverted USB2 changes + +[2.1.8 - July 14, 2010] + +* Ability to use both USB ports (requires updated IOS 202 - WARNING: older + versions of IOS 202 are NO LONGER supported) +* Hide non-ROM files +* Other minor improvements + +[2.1.7 - June 20, 2010] + +* USB improvements +* GameCube improvements - audio, SD Gecko, show thumbnails for saves +* Other minor changes + +[2.1.6 - May 19, 2010] + +* DVD support fixed +* Fixed some potential hangs when returning to menu +* Video/audio code changes +* Fixed scrolling text bug +* Other minor changes + +[2.1.5 - April 9, 2010] + +* Fix auto-save bug + +[2.1.4 - April 9, 2010] + +* Fixed issue with saves (GBA) and snapshots (GB) +* Most 3rd party controllers should work now (you're welcome!) +* Translation updates (German and Dutch) +* Other minor changes + +[2.1.3 - March 30, 2010] + +* Fixed ROM allocation. Should solve some unexplained crashes +* Numerous performance optimizations (thanks dancinninja!) +* DVD / USB 2.0 support via IOS 202. DVDx support has been dropped. It is + highly recommended to install IOS 202 via the included installer +* Multi-language support (only French translation is fully complete) +* Thank you to everyone who submitted translations +* SMB improvements/bug fixes +* Minor video & input performance optimizations +* Disabling rumble now also disables in-game rumbling +* Fixed saving of GB screen position adjustment + +[2.1.2 - December 23, 2009] + +* Numerous core optimizations (thanks dancinninjac!) +* File browser now scrolls down to the last game when returning to browser +* Auto update for those using USB now works +* Fixed scrollbar up/down buttons +* Minor optimizations + +[2.1.1 - December 7, 2009] + +* Save state corruption issues fixed + +[2.1.0 - December 2, 2009] + +* Fixed SMB (for real this time!) + +[2.0.9 - November 30, 2009] + +* Fixed SMB +* Added separate horizontal/vertical zoom options, and separate GB/GBA ones +* Improved scrolling timing - the more you scroll, the fast it goes +* Fixed reset button on Wii console - now you can reset multiple times +* APU optimization (dancinninjac) +* Minor code optimizations +* Reduce memory fragmentation - fixes out of memory crashes + +[2.0.8 - October 7, 2009] + +* Revamped filebrowser and file I/O +* Fixed MBC2 saving/loading +* Fixed some GB-Z80 instructions +* DVD loading in GameCube should work now (untested and unsupported) +* Many, many other bug fixes + +[2.0.7 - September 16, 2009] + +* Text rendering corrections +* SMB improvements +* Built with latest libraries +* Video mode switching now works properly +* Other minor bugfixes and cleanup + +[2.0.6 - July 22, 2009] + +* Fixed "No game saves found." message when there are actually saves. +* Fixed shift key on keyboard +* Text scrolling works again +* Change default prompt window selection to "Cancel" button + +[2.0.5 - July 9, 2009] + +* Faster SMB/USB browsing +* Last browsed folder is now remembered +* Fixed controller mapping reset button +* Fixed no sound on GameCube version +* Directory names are no longer altered +* Preferences now only saved on exit +* Fixed on-screen keyboard glitches +* SRAM auto-saved on power-off from within a game +* Prevent 7z lockups, better 7z error messages + +[2.0.4 - June 30, 2009] + +* Fixed auto-update +* Increased file browser listing to 10 entries, decreased font size +* Added text scrolling on file browser +* Added reset button for controller mappings +* Settings are now loaded from USB when loading the app from USB on HBC +* Fixed menu crashes caused by ogg player bugs +* Fixed memory card saving verification bug +* Fixed game savebrowser bugs +* Miscellaneous code cleanup/corrections + +[2.0.3 - May 30, 2009] + +* Fixed SD/USB corruption bug +* SMB works again +* GUI bugs fixed, GUI behavioral improvements +* GB Palette editing +* More built-in palettes +* Palettes now fade to white correctly instead of getting brighter +* Can now turn off palette colorizing +* Workaround for palette issue on Mega Man I GB - palette disabled +* Star Wars, TMNT, Lord Of The Rings, Castlevania Wii Controls +* Fix for WarioWare startup - Nunchuk C button or Wii Remote B button will now + make calibration easy by locking the gyroscope. +* Fixed issues with constant rumbling + +[2.0.2 - May 26, 2009] + +* Improved stability +* Fixed broken SDHC from HBC 1.0.2 update +* Fixed issues with returning to menu from in-game +* Add option to disable rumble +* Auto-determines if HBC is present - returns to Wii menu otherwise +* Unfiltered mode fixed +* Miscellaneous bugfixes + +[2.0.1 - April 30, 2009] + +* Multiple state saves now working +* Built with more stable libogc/libfat +* Fixed settings saving glitches +* Fixed Mortal Kombat GameCube controller bug +* Fixed Zelda DX palette bug +* Fixed Harry Potter 1-3 keyboard bug + +[2.0.0 - April 27, 2009] + +* New GX-based menu, with a completely redesigned layout. Has Wiimote IR + support, sounds, graphics, animation effects, and more +* Thanks to the3seashells for designing some top-notch artwork, to + Peter de Man for composing the music, and a special thanks to shagkur for + fixing libogc bugs that would have otherwise prevented the release +* Onscreen keyboard for changing save/load folders and network settings +* Menu configuration options (configurable exit button, wiimote orientation, + volumes) +* New save manager, allowing multiple saves and save browsing. Shows + screenshots for Snapshot saves, and save dates/times +* Added video shifting option +* Added video mode selection (recommended to leave on Automatic) +* USB Mouse support (buttons only) +* Keyboard shift key bug fixed +* Built-in 14 colour palettes for some monochrome gameboy games (Magnetic + Soccer, Malibu Beach Volleyball, Marble Madness, Metroid 2, Mortal Kombat, + Mortal Kombat II, Mortal Kombat 3, Mr. Do!) +* Rumble works in GBC games designed for rumble cartridges but shipped + without rumble cartridges, such as Disney's Tarzan for GBC +* Improved Mortal Kombat Wii Controls +* Mortal Kombat games now have many extra characters to choose +* Wii Controls for more Teenage Mutant Ninja Turtles games +* Improved Lego Star Wars controls +* Boktai menu now tells you when there can't be sun because it is night +* Minor bug fixes + +[1.0.9 - April 7, 2009] + +* Gamecube controller should no longer rumble constantly + +[1.0.8 - April 4, 2009] + +* "Match Wii Game" controls option! Games that have a Wii equivalent can be + played using the controls for that Wii game. For example all Zelda games + can be played with Twilight Princess controls. See the Instructions section + below for important details. +* Rotation/Tilt sensor games all work +* Solar sensors (Boktai 1/2/3) +* Rumble (except for games that rely on Gameboy Player) +* Keyboard +* PAL support, finally! +* New scaling options, choose how much stretching you want +* Colourised games now partially work but still have distortion +* "Corvette" no longer has a screwed up palette (but still crashes) +* Triggers net reconnection on SMB failure +* Source code refactored, and project file added +* Instructions section added to this readme file + +[1.0.7 - January 27, 2009] + +* Updated to VBA-M r847 +* Corrected sound interpolation +* Faster SD/USB - new read-ahead cache +* Removed trigger of back to menu for Classic Controller right joystick +* Fixed a bug with reading files < 2048 bytes +* Fixed GBA games on GameCube +* Fixed homebrew GBA games on GameCube +* Fixed some memory leaks, buffer overflows, etc +* Code cleanup, other general bugfixes + +[1.0.6 - December 24, 2008] + +* Fixed save state saving bug +* Fixed unstable SD card access +* Proper SD/USB hotswap (Wii only) +* Auto-update feature (Wii only) +* Rewritten SMB access - speed boost, NTLM now supported (Wii only) +* Improved file access code +* Resetting preferences now resets controls +* Minor bug fixes + +[1.0.5 - November 19, 2008] + +* SDHC works now +* Frameskipping tweaks +* Fixed snapshot loading issue +* Full widescreen support +* Changed scaling +* Zooming fixed (thanks eke-eke!) +* PAL timing changes - EURGB60 mode forced +* Wii - Added console/remote power button support +* Wii - Added reset button support (resets game) +* Wii - Settings file is now named settings.xml and is stored in the same + folder as the DOL (eg: apps/vbagx/settings.xml) +* GameCube - Added DVD motor off option +* GameCube - Fixed GBA loading issue + +[1.0.4 - October 28, 2008] + +* Complete port of VBA-M - now uses blaarg's new audio core, latest GB core +* Frameskipping improvements +* Sound processing improved - L-R channel reversal corrected, skipping fixed +* Saving problems fixed, game compatibility improved +* IPS/UPS/PPF patch support +* SD/USB hot-swapping! +* SDHC support +* Zoom setting saved +* Widescreen correction option +* GameCube support is back, including Qoob support! + +[1.0.3 - October 15, 2008] + +* New timing / frameskip algorithm - should (hopefully) work 100% better! +* Performance improvements - video threading, PPC core partly activated +* Video zooming option +* Unfiltered video option +* 7z support +* Loading progress bars added + +[1.0.2 - October 6, 2008] + +* New core! The core is now a custom combination of VBA-M and VBA 1.72 +* Added DVD, SMB, ZIP, GameCube MC support +* Faster USB/SD speeds +* Screen alignment and flickering problems fixed +* 128K save support added +* Better emulation speeds. Should now be nearly full speed all the time + for most games. +* Turbo speed feature. Mapped to right C-stick (classic controller & + Gamecube controller), and A+B for wiimote +* Controller mapping preferences bug fixed. Your preferences will reset + automatically to correct any problems in your preferences file +* Many other tweaks behind the scenes + +[1.0.1 - September 18, 2008] + +* GBA games now run at full speed +* Menu improvements, with spiffy new background +* Fixed L/R buttons - they work now + +[1.0.0 - September 16, 2008] + +* Now compiles with devkitpro r15 +* One makefile to make all versions +* Complete rewrite based on code from SNES9x GX +* Now has a menu! ROM selector, preferences, controller mapping, etc +* Wiimote, Nunchuk, and Classic controller support +* Button mapping for all controller types +* Full support for SD and USB +* Load/save preference selector. ROMs, saves, and preferences are + saved/loaded according to these +* 'Auto' settings for save/load - attempts to automatically determine + your load/save device(s) - SD, USB +* Preferences are loaded and saved in XML format. You can open + VBAGX.xml edit all settings, including some not available within + the program + +Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0OΧψo· SETUP & INSTALLATION ·oψΧO0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' + +Unzip the archive. You will find the following folders inside: + +apps Contains Homebrew Channel ready files + (see Homebrew Channel instructions below) + +vbagx Contains the directory structure required for storing + roms and saves. By default, roms are loaded from + "vbagx/roms/" and saves / preferences are stored in + "vbagx/saves/". + +-=[ Loading / Running the Emulator ]=- + +Wii - Via Homebrew Channel: +-------------------------------- +The most popular method of running homebrew on the Wii is through the Homebrew +Channel. If you already have the channel installed, just copy over the apps folder +included in the archive into the root of your SD card. + +Remember to also create the vbagx directory structure required. See above. + +If you haven't installed the Homebrew Channel yet, read about how to here: +http://hbc.hackmii.com/ + +Gamecube: +-------------------------------- +You can load VBAGX via sdload and an SD card in slot A, or by streaming +it to your Gamecube, or by booting a bootable DVD with VBAGX on it. +This document doesn't cover how to do any of that. + +Χ—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0OΧψo· INSTRUCTIONS ·oψΧO0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' +If you have upgraded from a previous version, the emulator may start with a +message that your preferences have been reset. You will need to set your +preferences how you want them. + +Otherwise the emulator will start at the main menu, which is a list of game +ROMs. There is also a settings button to choose how and where to load or +save files, and to change menu settings. + +Navigate the menu with the D-Pad, or the Wiimote pointer, and select options +with the A button. Press the B button to swap between controlling a list box +and controlling the buttons. Pressing the Home button will exit from the +main menu. You can choose what exiting will do by using the settings menu. + +Click on the logo to see the credits. + +When choosing a file, use left and right to go up or down a page. + +Once you choose a game, the game will start. But you can get back to a menu +by pressing Home. This takes you to the in-game menu, where you can save, +load, reset, or change settings. The settings apply to all games, not just +the current one. These settings are different from the settings on the main +menu. If you are playing a Boktai game with a solar sensor, there will also +be a fifth button which lets you change the weather. The sunlight is based +on the weather, the time of day, and the angle of your Wiimote. + +Saving and loading let you choose two kinds of save files. SRAM is the +normal kind of saving and loading that you have on a real gameboy. It only +saves up to the last checkpoint or savepoint in the game. Or you can save +a better way by using the emulator's special "Snapshot" feature which +saves the state of everything, exactly where you are up to. Loading a +Snapshot may erase your "SRAM (Auto)" so be careful. + +From the game menu you can return to the game by pressing Home again, or by +clicking on the "Close" button in the top right. Or to quit that game and +choose a different game, click on the "Main Menu" button. + +If you don't want to load ROMs from the SD card, you can go to the +settings menu and choose where to load from. You can load from SD cards, +USB memory sticks/hard drives, DVD (if you installed DVDX), gamecube memory +cards, or from shared folders over the network (this is called SMB). + +ROMs can be in ZIP files, but the ROM must be the first file in the ZIP. If +not, you will get an error. ROMs can also be in .7z files, or ordinary rom +files. + +Patches can be used to colourise a monochrome gameboy game, or to translate +a game into your language, or to stop the game from needing special hardware. +Search the internet for patches. Many games have been translated by fans. +They can be in IPS or UPS format. You don't need to patch anything yourself. +Just put the IPS or UPS file in the vbagx/roms folder along with the rom +itself. The patch must have the same name as the rom. Patches can not be put +inside the ZIP file. If a rom is zipped, you might need to check inside the +zip for the actual rom filename. + +Colourised games still have some distortion in this version, but it is +improved from the previous version, and better than VBA-M. Some unpatched +monochrome gameboy games have built-in palettes in this emulator and will +appear in colour. + +You must not use patched versions of Boktai roms! (Except for the translation +patch for Boktai 3, which is highly recommended). The patches are for old +emulators that don't support the solar sensor. VBA GX and NO$GBA support the +solar sensor natively, and the patch will stop them from working. + +You must also not use patched versions of WarioWare Twisted, Kirby's Tilt n +Tumble, or Yoshi's Universal Gravitation (Topsy Turvy). The original roms +are fully supported, and the patch will stop them from working. + +-=[ Controls ]=- + +See the website at http://www.wiibrew.org/wiki/VBA for better control +documentation, with illustrations and tables. + +The default controls are... + ++ = Gameboy Start Button +- = Gameboy Select Button +Home = Show emulator's game menu + +Wii Remote by itself: +Hold the Wii Remote sideways. +2 = Gameboy A Button +1 = Gameboy B Button +A = Gameboy R Button +B = Gameboy L Button + +Wii Remote + Nunchuk: +Hold the Nunchuk and ignore the Wii Remote. +Z = Gameboy A Button +C = Gameboy B Button + +Classic Controller: +B = Gameboy A Button +Y = Gameboy B Button +R = Gameboy R Button +L = Gameboy L Button + +You can configure the controls how you want from the controls menu. Different +controls will be used depending on what you have plugged into the Wii Remote. +Nunchuk means Nunchuk + Wii Remote. Gamecube controllers can +be used at the same time as Wii Remotes and all control the same player. +When configuring controls, press HOME to cancel. + +But the controls you choose will be overridden for certain games if you +choose "Match Wii Game" (or "Match Gamecube Game" on a Gamecube) and you have +the appropriate expansion plugged in. If the game does not have special Wii +controls, then the controls you chose will be used. + +Gameboy and Gameboy colour games don't have L and R buttons. Those buttons +only work in Gameboy Advance games. + +In addition to the controls you can configure, these other controls apply: + +HOME, Escape: returns you to the emulator's game menu. Then press B to go +to the main menu and B again to return to the game. +A+B, Spacebar, or right analog stick: fast forward +Right analog stick: zoom (if enabled) + +-=[ Super Game Boy borders ]=- + +VBA-GX has supported Super Game Boy borders since 2.3.1. You can enable this +feature in the Emulation settings on the main menu. + +Borders can be loaded from two locations: +* PNG files in the borders folder (by default, /vbagx/borders) +* The game itself + +Borders will only be loaded from the game itself when the emulator is running +in Super Game Boy mode, and the border setting in Emulation settings is set to +"From game (SGB only)". (You can also use the Emulation settings menu to +force SGB mode even for Game Boy Color games.) If the borders folder exists, +but no border for the game is present, the loaded Super Game Boy border will +be written to a .png file, which can be loaded later in "From .png file" mode. + +In addition, if the borders folder exists but there is no border for the game, +the first border loaded from the game will be written to a PNG file so it can +be loaded in the future (even in Game Boy Color mode.) This means after you +run a game once in SGB mode, you can then use the same border in GBC mode. + +If the border setting is set to "From .png file", borders will be loaded +from the borders folder. Borders can be up to 640x480 and will work for both +Game Boy (Color) and Game Boy Advance games. + +For both loading and saving, the PNG filename is [TITLE].png, where [TITLE] +is the ROM title defined at 0x134 (for GB games) or 0xA0 (for GBA games). For +example, POKEMON_SFXAAXE.png will be loaded for Pokιmon Silver. If no PNG file +by that name exists, VBA-GX will try loading default.png (for GB games) or +defaultgba.png (for GBA games) instead. + +Since the borders are rendered along with the video output of the game, the +pixels in the border will be the same size as game pixels. This means that +a Game Boy game will appear in the middle 160x144 pixels of the border, and a +Game Boy Advance game will appear in the middle 240x160 pixels, regardless of +the resolution of the border PNG image. + +-=[ Match Wii Controls ]=- + +Special Wii controls exist for the following games: + +These Zelda games can be played with Twilight Princess controls: +The Legend Of Zelda, Zelda 2, A Link To The Past, Link's Awakening (DX), +Oracle of Ages, Oracle of Seasons, Minish Cap + +These Mario games can be played with Mario Galaxy controls: +Super Mario Bros., Super Mario Bros. DX, Super Mario 2, Super Mario (2) +Advance, Super Mario 3, Super Mario World, Yoshi's Island, +Yoshi's Universal Gravitation (Topsy Turvy) + +Mario Kart can be (sort of) played with Mario Kart wii controls, but it +doesn't work very well. + +These Metroid games can be played with Metroid Prime 3 controls: +Metroid Zero Mission, Metroid 1, Metroid 2, Metroid Fusion + +These Mortal Kombat games can be played with Mortal Kombat Armageddon controls: +Mortal Kombat, Mortal Kombat II, Mortal Kombat 3, Mortal Kombat 4, Mortal +Kombat Advance, Mortal Kombat Deadly Alliance, Mortal Kombat Tournament +Edition + +These Lego games can be played with Lego Star Wars the Complete Saga +controls: +Lego Star Wars The Video Game, Lego Star Wars The Original Trilogy + +These Teenage Mutant Ninja Turtles games can be played with TMNT Wii controls: +TMNT, Teenage Mutant Ninja Turtles, Fall of the Foot Clan, Back from the Sewers, +Radical Rescue + +These Harry Potter games can be played with Harry Potter and the Order of +the Phoenix Wii controls: +Harry Potter 1, Harry Potter 1 GBC, Harry Potter 2, Harry Potter 2 GBC, +Harry Potter 3, Harry Potter 4, Harry Potter 5 + +These Medal Of Honour games can be played with Medal Of Honour Wii controls: +Medal Of Honour Underground, Medal Of Honour Infiltrator + +One Piece can be played with One Piece Unlimited Adventure controls. + +Boktai 1, Boktai 2, Boktai 3, and Kirby's Tilt n Tumble, and WarioWare Twisted +can be played with controls designed for them. + +-=[ Zelda, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Zelda games use the same controls as Twilight Princess on the Wii or +Gamecube. You can also connect a Classic Controller to use similar controls +to the Ocarina Of Time for the Virtual Console, but with the R trigger +acting as the B button and an inventory like Twilight Princess. With nothing +plugged in to the Wii Remote, your configured controls are used instead. + +The Wii Zelda controls are: +=========================== + +Swing your Wii Remote to draw or swing your sword. Press A to put your sword +away again. The 2 handed sword can't be drawn this way, and must be drawn +manually from the items menu, but you can swing it like normal. + +Shake your Nunchuk to do a spin attack. + +Use the Z Button to Z-Target and to draw and use your shield. While +Z-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for Z-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +pulling things, etc. It will also put away your sword or shield. In Zelda 2, +it will jump. + +Use the C Button to fast forward. It was originally the camera button in +Twilight Princess. + +Press the B Button to use the currently selected item. 3 other items will be +mapped to Left, Down, and Right D-Pad buttons. Swap the currently selected +item with one of those items by pressing that D-Pad button. The three slots +correspond to the first 3 slots in your inventory. In Minish Cap, the D-Pad +buttons use the item directly instead of swapping it with the B Button, and +the B Button is the same as the down button. In Minish Cap the left item is +always the Kinstones and the down and right items correspond to the B and A +slots. + +Up on the D-Pad talks to Midna, or to your hat. It will take you to the save +screen in Link's Awakening, or to the secondary items screen in the Oracle +games. + +The 1 Button goes to the Map screen. +The - Button goes to the Items screen. +The + Button goes to the Quest Status screen + +On the Items screen, choose an item and then press either the B Button or the +D-Pad button to move it to that slot. The change may not be visible until you +go to another screen and back. In Link's Awakening you can toggle Bomb +Arrows by choosing the bombs and pressing Z. It will rumble for a short time +when bomb arrows are deactivated, and for a long time when bomb arrows are +activated. You still need to equip the bow to use bomb arrows. In Minish Cap +you should be able to use the IR pointer function to select items. + +The Gamecube controller Zelda controls are: +=========================================== + +B is the sword button. Use it to draw or swing your sword. Hold B for a spin +attack. Press A to put the sword away again. The 2 handed sword can't be +drawn this way, and must be selected manually from the items screen, but can +be swung with this (or any other) button. + +Use the L Trigger to L-Target and to draw and use your shield. While +L-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for L-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +etc. It will also put away your sword or shield. In Zelda 2, it will jump. + +Use the R Trigger to pull on blocks or walls, or to lift things. You must +have a bracelet or gloves to lift some objects. The bracelet or gloves will +be equipped automatically. This feature is unique to the Gamecube controller. + +Use the right analog stick to fast forward. It was originally the camera +control in Twilight Princess. + +Press the X or Y buttons to use the two equipped items. These two items both +share the B slot, except in Minish Cap where one is in the A slot. The item +that was not used last will be in the first slot in your inventory. + +Right on the D-Pad takes you to the map. +Up on the D-Pad takes you to the items screen. +Start takes you to the quest status screen. + +The Z trigger talks to Midna, or to your hat. It will take you to the save +screen in Link's Awakening, or to the secondary items screen in the Oracle +games. + +The Classic controller Zelda controls are: +========================================== + +B is the sword button. Use it to draw or swing your sword. Hold B for a spin +attack. Press A to put the sword away again. The 2 handed sword can't be +drawn this way, and must be selected manually from the items screen, but can +be swung with this (or any other) button. + +Use the L Trigger to L-Target and to draw and use your shield. While +L-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for L-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +pulling, etc. It will also put away your sword or shield. In Zelda 2, it +will jump. + +Use the ZL Button to fast forward. + +Press the R Button to use the currently selected item. 3 other items will be +mapped to Left, Down, and Right on the right analog stick. They are also +mapped to ZR, Y, and X. Swap the currently selected item with one of those +items by pressing that button or direction. The three slots correspond to +the first 3 slots in your inventory. In Minish Cap, the D-Pad buttons use the +item directly instead of swapping it with the B Button, and the B Button is +the same as the down button. In Minish Cap the left item is always the +Kinstones and the down and right items correspond to the B and A slots. + ++ (Start) takes you to the subscreens. +- (Select) takes you to the map or changes subscreens. + +Up on the analog stick talks to Midna, or to your hat. + + +-=[ Mario, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Mario or Yoshi games use the same controls as Super Mario Galaxy on the +Wii. You can also connect a Classic Controller to use similar controls to +Super Mario World on the SNES. + +The Wii Mario controls are: +=========================== + +Shake the Wii Remote to do a spin attack, or to shoot fireballs when you are +fire Mario. In some games that have a spin attack, you will need to use the +B Button instead to shoot fireballs. You can also dismount Yoshi by shaking. + +Walk by moving the joystick a little, run by moving the joystick a lot. + +A = jump +B = shoot, run, hold on to things, yoshi's tongue, etc. +Z = crouch or lay egg. Press Z while in the air to butt stomp. +C = camera. Hold C to look around with the joystick. +D-Pad = look around, or walk in some games ++ = pause +1 = throw egg if you are Yoshi + +The Classic Controller Mario controls are: +========================================== + +Walk by moving the joystick a little, run by moving the joystick a lot. + +B = jump +A = spin attack +X/Y = shoot, run, hold on to things, yoshi's tongue, etc. +ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp. ++ = pause +L/R = look around (if the game supports it) +ZR = fast forward (8-bit Game Boy only) + +In Super Mario World and Super Mario Land 2, you can use the A or R +buttons for a spin jump. + + +-=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The controls are the same as all other Mario or Yoshi games, except that +tilting the Wii Remote tilts the world and the screen. This affects +everything in the world and also how you move. + + +-=[ Metroid, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Metroid games use the same controls as Metroid Prime 3: Corruption on +the Wii. You aim up and down by pointing the Wii Remote up and down. + +The Wii Metroid controls are: +============================= +Aim up and down by pointing the Wii Remote up and down. + +Flick the Wii remote up while in Morph Ball to spring jump. + +A = shoot +B = jump +Down on D-Pad = fire missile +C = toggle Morph Ball +- = start ++ = toggle super missiles +1 = map +2 = hint + + +-=[ TMNT, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The TMNT games (except Battle Nexus) use the same controls as TMNT on Wii, +or GameCube. With a Classic Controller they use the same controls as on +the Playstation version. + +The Wii TMNT controls are: +========================== +Shake the Wii Remote to attack or to throw away a weapon if +in the air. Also shake to pick up a weapon. + +Shake the Nunchuk to do a spin kick. + +A = jump +B = swap turtle, or charge attack +B while pointing up = super family move +C = roll +Z = special move + +-=[ Boktai, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The 3 Boktai games use special controls that I created. They are not based on +anything, since the real game uses a solar sensor. + +The controls are the same with or without a Nunchuk. + +The Wii Boktai controls are: +============================ + +Point your Wii Remote at the sky to quickly charge your Gun Del Sol. Point +your Wii Remote at the ground to block the sunlight and prevent it from +charging or overheating. Or hold it like normal to use it like normal. + +Press Home to set the real life weather in the emulator's game menu. Note +that if it is night time in real life, there will not be any sun, regardless +of what you set the weather to. Please set the weather honestly or it spoils +the fun. Note that maximum sun is not actually the best, since it rots fruit, +and overheats your gun. The weather must be set each time you play, it is not +saved. + +Swing your Wii Remote to swing your sword or other weapon, if you have one. + +D-Pad or Nunchuk joystick walks. + +Press B to fire your Gun Del Sol. + +A = read signs, open chests, talk to people +C or 2 = look around, or change subscreen (R) ++ = start +- = select +Z or 1 = change element, or change subscreen (L) +1 (if Nunchuk plugged in) = fast forward + +-=[ WarioWare Twisted, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +WarioWare Twisted uses similar controls to the Gameboy game. + +The Wii WarioWare Twisted controls are: +======================================= + +Rotate the Wii Remote to rotate. + +Hold Z to lock the current menu item. + +A = Select +B = Cancel ++ = Start + +-=[ Kirby's Tilt n Tumble, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +Kirby's Tilt n Tumble uses similar controls to the Gameboy game. + +The Kirby Tilt n Tumble controls are: +===================================== + +Tilt the Wii Remote to tilt the world. Shake the Wii Remote to flick Kirby +and the monsters up into the air. + +A = shoot yourself out of holes in the ground, or jump from clouds. + +-=[ Mortal Kombat, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Mortal Kombat games use the same controls as Mortal Kombat Armaggedon +for the Wii, except that special moves gestures are not implemented yet. + +The Mortal Kombat Wii controls are: +=================================== + +Use the Nunchuk joystick to move and jump. + +D-Pad left = Low Punch +D-Pad up = High Punch +D-Pad down = Low Kick +D-Pad right = High Kick +Z = block +A = throw +C = change style, run, change costume or character ++ = pause +- = change costume or character + +-=[ Lego Star Wars, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +Both Lego Star Wars games use the same controls as Lego Star Wars: The +Complete Saga for the Wii. + +The Lego Star Wars Wii controls are: +==================================== +Swing the Wii Remote to swing your lightsaber. +Flick the Wii Remote up to grapple. + +A = Jump +B = Shoot +Z = Use the force, build lego +C = Change characters, talk to people +- = force power, special ability ++ = start +1/2 = fast forward + +-=[ Harry Potter, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All the Harry Potter games use the same controls as Harry Potter & The Order +Of The Phoenix on the Wii. Spell gestures are not supported yet. + +The Harry Potter Wii controls are: +================================== +Wave the Wii Remote to cast a spell. +Nunchuk joystick walks. +D-Pad changes subscreen in the map and navigates menu. +In Harry Potter and the Order of the Phoenix you must use the IR Pointer +to select where to cast a spell. + +A = Talk, open door, push button, interract, etc. / Jinx +B = Use your wand / charm / cancel +Z = run (fast forward) / sneak +C = show location name / flute / jump +- = Maurauders map / Tasks ++ = pause / menu +1/2 = change spells + +-=[ Medal of Honour, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All the Medal of Honour games use the same controls as various +Medal of Honour games and modes on the Wii. + +The Medal of Honour Wii controls are: +===================================== + +In Medal of Honour Underground you turn by aiming with the Wii Remote IR +pointer on the screen like any FPS game. In Medal of Honour Infiltrator, +you don't. + +Swing the Wiimote up to reload. +Move with the Nunchuk joystick. + +B = shoot +- = use ++ = pause, objectives, menu +2 / D-Pad Up = reload +D-Pad Left/Right = change weapons +D-Pad Down = toggle crouch +C = strafe +1 = run + +-=[ One Piece, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +One Piece uses the same controls as One Piece Unlimited Adventure on the Wii +or One Piece Grand Adventure (and others) on the Gamecube. + +The One Piece Wii controls are: +=============================== + +A = attack +B = jump +- = change character ++ = pause +C = dash (double click and hold) +Z = grab +2 = fast forward +1 = select (maybe does nothing) + +The One Piece Gamecube controls are: +=============================== + +A = attack +X = attack up +Y = jump +B = grab +R Trigger = change character +start = pause +L Trigger = dash (double click and hold) +Z = grab +right analog stick = fast forward +1 = select (maybe does nothing) + +-=[ Kid Dracula, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +(There's no Kid Dracula game for the Wii, but this is a good opportunity to +show off some fancy memory-swapping tricks. -libertyernie) + +The Kid Dracula Wii controls (remote + nunchuk) are: +==================================================== + +A = jump +B = use selected weapon +Z = use NOR weapon (fireball) +C = use BAT weapon (turn into bat for 5 sec) ++ = pause +- = switch item +1/2 = fast forward + +The Kid Dracula Classic Controller controls are: +================================================ + +A/B = jump +Y = use selected weapon +X = use NOR weapon (fireball) +R/ZR = use BAT weapon (turn into bat for 5 sec) ++ = pause +- = switch item +1/2 = fast forward + +In Kid Dracula, pressing the "fire" button will always shoot a small fireball, +but holding the button for a second or so to charge up the shoot lets you use +whichever item is selected. + +Pressing B (nunchuk) or Y (classic) will switch back to whatever item was +selected before you pressed Z/C (nunchuk) or X/R/ZR (classic), unless you have +switched items since then. + +Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ + +-=[ Credits ]=- + + Coding & menu design Tantric + Codebase update & Goomba libertyernie + Menu screenshots cebolleto + GBA tiled rendering bgK (for RetroArch) + Additional coding Carl Kenner, dancinninjac + Menu artwork the3seashells + Menu sound Peter de Man + + ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ + VBA GameCube/Wii SoftDev, emukidid + + Visual Boy Advance - M VBA-M Team + Visual Boy Advance Forgotten + libogc/devkitPPC shagkur & wintermute + FreeTypeGX Armin Tamzarian + + And many others who have contributed over the years! + +Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ + + VBAGX Web Site + https://github.com/dborth/vbagx + +Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€°`°€ψ,Έ,ψ€°`°€ψ,ΈΈ,ψ€ diff --git a/source/vba/System.h b/source/vba/System.h index 87bf6e4..bed32b4 100644 --- a/source/vba/System.h +++ b/source/vba/System.h @@ -1,21 +1,23 @@ #ifndef SYSTEM_H #define SYSTEM_H + #include "common/Types.h" + #include class SoundDriver; struct EmulatedSystem { - // main emulation function - void (*emuMain)(int); - // reset emulator - void (*emuReset)(); - // clean up memory - void (*emuCleanUp)(); - // load battery file - bool (*emuReadBattery)(const char *); - // write battery file - bool (*emuWriteBattery)(const char *); + // main emulation function + void (*emuMain)(int); + // reset emulator + void (*emuReset)(); + // clean up memory + void (*emuCleanUp)(); + // load battery file + bool (*emuReadBattery)(const char *); + // write battery file + bool (*emuWriteBattery)(const char *); #ifdef __LIBRETRO__ // load state bool (*emuReadState)(const u8*, unsigned); @@ -27,23 +29,24 @@ struct EmulatedSystem { // save state bool (*emuWriteState)(const char *); #endif - // load memory state (rewind) - bool (*emuReadMemState)(char *, int); - // write memory state (rewind) - bool (*emuWriteMemState)(char *, int); - // write PNG file - bool (*emuWritePNG)(const char *); - // write BMP file - bool (*emuWriteBMP)(const char *); - // emulator update CPSR (ARM only) - void (*emuUpdateCPSR)(); - // emulator has debugger - bool emuHasDebugger; - // clock ticks to emulate - int emuCount; + // load memory state (rewind) + bool (*emuReadMemState)(char *, int); + // write memory state (rewind) + bool (*emuWriteMemState)(char *, int); + // write PNG file + bool (*emuWritePNG)(const char *); + // write BMP file + bool (*emuWriteBMP)(const char *); + // emulator update CPSR (ARM only) + void (*emuUpdateCPSR)(); + // emulator has debugger + bool emuHasDebugger; + // clock ticks to emulate + int emuCount; }; extern void log(const char *,...); + extern bool systemPauseOnFrame(); extern void systemGbPrint(u8 *,int,int,int,int,int); extern void systemScreenCapture(int); @@ -52,6 +55,11 @@ extern void systemDrawScreen(); extern bool systemReadJoypads(); // return information about the given joystick, -1 for default joystick extern u32 systemReadJoypad(int); +// this function should turn on or off rumble on the gamepad +extern void systemCartridgeRumble(bool); +extern void systemPossibleCartridgeRumble(bool); +// This should be called once per frame +extern void updateRumbleFrame(); extern u32 systemGetClock(); extern void systemMessage(int, const char *, ...); extern void systemSetTitle(const char *); @@ -60,13 +68,14 @@ extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length); extern void systemOnSoundShutdown(); extern void systemScreenMessage(const char *); extern void systemUpdateMotionSensor(); -extern int systemGetSensorX(); -extern int systemGetSensorY(); +extern int systemGetSensorX(); +extern int systemGetSensorY(); extern bool systemCanChangeSoundQuality(); extern void systemShowSpeed(int); extern void system10Frames(int); extern void systemFrame(); extern void systemGbBorderOn(); + extern void Sm60FPS_Init(); extern bool Sm60FPS_CanSkipFrame(); extern void Sm60FPS_Sleep(); @@ -78,8 +87,10 @@ extern void winlog(const char *,...); #endif extern void (*dbgOutput)(const char *s, u32 addr); extern void (*dbgSignal)(int sig,int number); + extern u16 systemColorMap16[0x10000]; -extern u32 systemColorMap32[0x10000]; +//extern u32 systemColorMap32[0x10000]; +extern u32 *systemColorMap32; extern u16 systemGbPalette[24]; extern int systemRedShift; extern int systemGreenShift; @@ -90,6 +101,8 @@ extern int systemVerbose; extern int systemFrameSkip; extern int systemSaveUpdateCounter; extern int systemSpeed; + #define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_NOT_UPDATED 0 -#endif // SYSTEM_H + +#endif // SYSTEM_H diff --git a/source/vba/Util.cpp b/source/vba/Util.cpp index 2f742ae..2529f32 100644 --- a/source/vba/Util.cpp +++ b/source/vba/Util.cpp @@ -26,7 +26,6 @@ extern "C" { #include "common/memgzio.h" } -#include "gba/gbafilter.h" #include "gb/gbGlobals.h" #ifndef _MSC_VER @@ -39,7 +38,7 @@ extern int systemGreenShift; extern int systemBlueShift; extern u16 systemColorMap16[0x10000]; -extern u32 systemColorMap32[0x10000]; +extern u32 *systemColorMap32; static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL; static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL; @@ -657,6 +656,7 @@ long utilGzMemTell(gzFile file) return memtell(file); } +#ifndef GEKKO void utilGBAFindSave(const u8 *data, const int size) { u32 *p = (u32 *)data; @@ -743,3 +743,4 @@ bool utilFileExists( const char *filename ) return true; } } +#endif diff --git a/source/vba/apu/Blip_Buffer.cpp b/source/vba/apu/Blip_Buffer.cpp index 5eacc06..bebb412 100644 --- a/source/vba/apu/Blip_Buffer.cpp +++ b/source/vba/apu/Blip_Buffer.cpp @@ -29,7 +29,7 @@ int const silent_buf_size = 1; // size used for Silent_Blip_Buffer Blip_Buffer::Blip_Buffer() { - factor_ = (blip_ulong)LONG_MAX; + factor_ = LONG_MAX; buffer_ = 0; buffer_size_ = 0; sample_rate_ = 0; @@ -126,7 +126,7 @@ Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const { - double ratio = (double) sample_rate_ / rate; + double ratio = (double)(sample_rate_) / double(rate); blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large return (blip_resampled_time_t) factor; @@ -226,15 +226,17 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d treble = 5.0; double const maxh = 4096.0; - double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) ); + double const rolloff = pow( 10.0, treble / (maxh * 20.0 * (1.0 - cutoff)) ); double const pow_a_n = pow( rolloff, maxh - maxh * cutoff ); - double const to_angle = PI / 2 / maxh / oversample; + double const to_angle = PI / (2.0 * maxh * oversample); for ( int i = 0; i < count; i++ ) { - double angle = ((i - count) * 2 + 1) * to_angle; - double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle ); - double cos_nc_angle = cos( maxh * cutoff * angle ); - double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle ); + double angle = double(((i - count)<<1) + 1) * to_angle; + double maxhAngle = maxh * angle; + double c = rolloff * cos( maxhAngle - angle ) - cos( maxhAngle ); + double cos_nc_angle = cos( maxhAngle * cutoff ); + double cos_nc1_angle = cos( maxhAngle * cutoff - angle ); + double cos_angle = cos( angle ); c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle; @@ -250,7 +252,7 @@ void blip_eq_t::generate( float* out, int count ) const { // lower cutoff freq for narrow kernels with their wider transition band // (8 points->1.49, 16 points->1.15) - double oversample = blip_res * 2.25 / count + 0.85; + double oversample = blip_res * 2.25 / double(count) + 0.85; double half_rate = sample_rate * 0.5; if ( cutoff_freq ) oversample = half_rate / cutoff_freq; @@ -268,7 +270,9 @@ void Blip_Synth_::adjust_impulse() { // sum pairs for each phase and add error correction to end of first half int const size = impulses_size(); - for ( int p = blip_res; p-- >= blip_res / 2; ) + + int blipRes2 = blip_res >> 1; + for ( int p = blip_res; p-- >= blipRes2; ) { int p2 = blip_res - 2 - p; long error = kernel_unit; @@ -290,9 +294,11 @@ void Blip_Synth_::adjust_impulse() void Blip_Synth_::treble_eq( blip_eq_t const& eq ) { - float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2]; + int blipRes2 = blip_res >> 1; - int const half_size = blip_res / 2 * (width - 1); + float fimpulse [blipRes2 * (blip_widest_impulse_ - 1) + blip_res * 2]; + + int const half_size = blipRes2 * (width - 1); eq.generate( &fimpulse [blip_res], half_size ); int i; @@ -302,25 +308,25 @@ void Blip_Synth_::treble_eq( blip_eq_t const& eq ) fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i]; // starts at 0 - for ( i = 0; i < blip_res; i++ ) + for ( i = 0; i < blip_res; ++i ) fimpulse [i] = 0.0f; // find rescale factor double total = 0.0; - for ( i = 0; i < half_size; i++ ) + for ( i = 0; i < half_size; ++i ) total += fimpulse [blip_res + i]; //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB //double const base_unit = 37888.0; // allows treble to +5 dB double const base_unit = 32768.0; // necessary for blip_unscaled to work - double rescale = base_unit / 2 / total; + double rescale = base_unit / (2 * total); kernel_unit = (long) base_unit; // integrate, first difference, rescale, convert to int double sum = 0.0; double next = 0.0; int const size = this->impulses_size(); - for ( i = 0; i < size; i++ ) + for ( i = 0; i < size; ++i ) { impulses [i] = (short) (int) floor( (next - sum) * rescale + 0.5 ); sum += fimpulse [i]; @@ -355,7 +361,7 @@ void Blip_Synth_::volume_unit( double new_unit ) // if unit is really small, might need to attenuate kernel while ( factor < 2.0 ) { - shift++; + ++shift; factor *= 2.0; } @@ -411,7 +417,7 @@ long Blip_Buffer::read_samples( blip_sample_t* out_, long max_samples, int stere blip_long s = BLIP_READER_READ( reader ); BLIP_READER_NEXT_IDX_( reader, bass, offset ); BLIP_CLAMP( s, s ); - out [offset * 2] = (blip_sample_t) s; + out [offset << 1] = (blip_sample_t) s; } while ( ++offset ); } diff --git a/source/vba/apu/Effects_Buffer.cpp b/source/vba/apu/Effects_Buffer.cpp index b65d860..deff3f0 100644 --- a/source/vba/apu/Effects_Buffer.cpp +++ b/source/vba/apu/Effects_Buffer.cpp @@ -505,7 +505,7 @@ void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count ) int bufs_remain = bufs_size; do { - if ( buf->non_silent() && ( buf->echo == !!echo_phase ) ) + if ( buf->non_silent() && ( buf->echo == (bool)echo_phase ) ) { stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos]; int const bass = BLIP_READER_BASS( *buf ); diff --git a/source/vba/gb/GB.cpp b/source/vba/gb/GB.cpp index 01bea43..315b697 100644 --- a/source/vba/gb/GB.cpp +++ b/source/vba/gb/GB.cpp @@ -1433,10 +1433,12 @@ void gbWriteMemory(register u16 address, register u8 value) int paletteHiLo = (v & 0x01); // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + // CAK - The following check has to be commented out for + // colourised roms like Metroid 2 DX + //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) { gbMemory[0xff69] = value; gbPalette[paletteIndex] = (paletteHiLo ? @@ -1487,10 +1489,12 @@ void gbWriteMemory(register u16 address, register u8 value) paletteIndex += 32; // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + // CAK - The following check has to be commented out for + // colourised roms like Metroid 2 DX + //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) { gbMemory[0xff6b] = value; gbPalette[paletteIndex] = (paletteHiLo ? @@ -1567,7 +1571,7 @@ u8 gbReadOpcode(register u16 address) if(address < 0x8000) return gbMemoryMap[address>>12][address&0x0fff]; - if (address < 0xa000) + if(address < 0xa000) { // A lot of 'ugly' checks... But only way to emulate this particular behaviour... if ( @@ -1683,13 +1687,13 @@ u8 gbReadOpcode(register u16 address) if (gbCgbMode) { // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) return (gbMemory[address]); - else - return 0xff; + //else + // return 0xff; } else return 0xff; @@ -1733,8 +1737,7 @@ u8 gbReadMemory(register u16 address) if(address < 0x8000) return gbMemoryMap[address>>12][address&0x0fff]; - - if (address < 0xa000) + if(address < 0xa000) { // A lot of 'ugly' checks... But only way to emulate this particular behaviour... if ( @@ -1759,8 +1762,7 @@ u8 gbReadMemory(register u16 address) ) ) ) - return gbMemoryMap[address >> 12][address & 0x0fff]; - + return gbMemoryMap[address>>12][address&0x0fff]; return 0xff; } @@ -1961,13 +1963,13 @@ u8 gbReadMemory(register u16 address) if (gbCgbMode) { // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) return (gbMemory[address]); - else - return 0xff; + //else + // return 0xff; } else return 0xff; @@ -2124,7 +2126,7 @@ void gbCPUInit(const char *biosFileName, bool useBiosFile) useBios = false; if (useBiosFile) { - int size = 0x100; +/* int size = 0x100; if(utilLoad(biosFileName, CPUIsGBBios, bios, @@ -2133,7 +2135,7 @@ void gbCPUInit(const char *biosFileName, bool useBiosFile) useBios = true; else systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size")); - } + }*/ } } @@ -2149,12 +2151,12 @@ void gbGetHardwareType() } } - if((gbCgbMode == 0) && (gbRom[0x146] == 0x03)) { + if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) { if(gbEmulatorType == 0 || gbEmulatorType == 2 || gbEmulatorType == 5) gbSgbMode = 1; - gbCgbMode = 0; + gbCgbMode = 0; } gbHardware = 1; // GB @@ -2172,7 +2174,9 @@ void gbGetHardwareType() void gbReset() { + systemCartridgeRumble(false); gbGetHardwareType(); + gbPaletteReset(); oldRegister_WY = 146; gbInterruptLaunched = 0; @@ -2468,7 +2472,7 @@ void gbReset() gbTimerOn = false; if(gbCgbMode) { - for (i = 0; i<0x20; i++) + for (int i = 0; i<0x20; i++) gbPalette[i] = 0x7fff; // This is just to show that the starting values of the OBJ palettes are different @@ -2586,12 +2590,12 @@ void gbReset() } } else { if(gbSgbMode) { - for(i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; + for(int i = 0; i < 12; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*12+i]; } - for(i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; + for(int i = 0; i < 12; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*12+i]; } GBTIMER_MODE_0_CLOCK_TICKS = 256; @@ -2645,6 +2649,8 @@ void gbReset() memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); gbDataMBC5.mapperROMBank = 1; + if (gbRomType >= 0x1c && gbRomType<=0x1e) + gbDataMBC5.isRumbleCartridge = 1; memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); gbDataHuC1.mapperROMBank = 1; @@ -2746,7 +2752,7 @@ void gbWriteSaveMBC2(const char * name) return; } - fwrite(gbMemoryMap[0x0a], + fwrite(&gbMemoryMap[0x0a], 1, 512, file); @@ -2928,7 +2934,7 @@ bool gbReadSaveMBC2(const char * name) return false; } - size_t read = fread(gbMemoryMap[0x0a], + size_t read = fread(&gbMemoryMap[0x0a], 1, 512, file); @@ -4007,16 +4013,18 @@ bool gbReadSaveState(const char *name) bool gbWritePNGFile(const char *fileName) { - if(gbBorderOn) +/* if(gbBorderOn) return utilWritePNGFile(fileName, 256, 224, pix); - return utilWritePNGFile(fileName, 160, 144, pix); + return utilWritePNGFile(fileName, 160, 144, pix);*/ + return false; } bool gbWriteBMPFile(const char *fileName) { - if(gbBorderOn) +/* if(gbBorderOn) return utilWriteBMPFile(fileName, 256, 224, pix); - return utilWriteBMPFile(fileName, 160, 144, pix); + return utilWriteBMPFile(fileName, 160, 144, pix);*/ + return false; } void gbCleanUp() @@ -4081,10 +4089,10 @@ bool gbLoadRom(const char *szFile) systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - gbRom = utilLoad(szFile, +/* gbRom = utilLoad(szFile, utilIsGBImage, NULL, - size); + size);*/ if(!gbRom) return false; @@ -4513,6 +4521,7 @@ void gbEmulate(int ticksToStop) } #endif + u16 oldPCW = PC.W; if(IFF & 0x80) { diff --git a/source/vba/gb/gbMemory.cpp b/source/vba/gb/gbMemory.cpp index 12ce2b5..3d8da94 100644 --- a/source/vba/gb/gbMemory.cpp +++ b/source/vba/gb/gbMemory.cpp @@ -583,10 +583,18 @@ void mapperMBC5ROM(u16 address, u8 value) gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; } break; - case 0x4000: // RAM bank select - if(gbDataMBC5.isRumbleCartridge) + case 0x4000: // RAM bank select, plus rumble + // Some games support rumble, such as Disney Tarzan, but aren't on a + // rumble cartridge. As long as the RAM is less than or equal to 256Kbit + // we know that the last address line is not used for real RAM addresses, + // so it must be a rumble signal instead. + if(gbDataMBC5.isRumbleCartridge) { + systemCartridgeRumble(value & 0x08); value &= 0x07; - else + } else if (gbRamSizeMask <= 0x7FFF) { + systemPossibleCartridgeRumble(value & 0x08); + value &= 0x07; + } else value &= 0x0f; if(value == gbDataMBC5.mapperRAMBank) break; diff --git a/source/vba/gba/GBA.cpp b/source/vba/gba/GBA.cpp index b728bfe..3e9c637 100644 --- a/source/vba/gba/GBA.cpp +++ b/source/vba/gba/GBA.cpp @@ -521,11 +521,11 @@ void CPUUpdateWindow0() int x01 = WIN0H & 255; if(x00 <= x01) { - for(int i = 0; i < 240; i++) { + for(int i = 0; i < 240; ++i) { gfxInWin0[i] = (i >= x00 && i < x01); } } else { - for(int i = 0; i < 240; i++) { + for(int i = 0; i < 240; ++i) { gfxInWin0[i] = (i >= x00 || i < x01); } } @@ -537,11 +537,11 @@ void CPUUpdateWindow1() int x01 = WIN1H & 255; if(x00 <= x01) { - for(int i = 0; i < 240; i++) { + for(int i = 0; i < 240; ++i) { gfxInWin1[i] = (i >= x00 && i < x01); } } else { - for(int i = 0; i < 240; i++) { + for(int i = 0; i < 240; ++i) { gfxInWin1[i] = (i >= x00 || i < x01); } } @@ -667,7 +667,6 @@ bool CPUWriteState(const char *file) return res; } - bool CPUWriteMemState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -1325,12 +1324,12 @@ bool CPUReadBatteryFile(const char *fileName) bool CPUWritePNGFile(const char *fileName) { - return utilWritePNGFile(fileName, 240, 160, pix); + return false; //utilWritePNGFile(fileName, 240, 160, pix); } bool CPUWriteBMPFile(const char *fileName) { - return utilWriteBMPFile(fileName, 240, 160, pix); + return false; //utilWriteBMPFile(fileName, 240, 160, pix); } bool CPUIsZipFile(const char * file) @@ -1494,7 +1493,7 @@ int CPULoadRom(const char *szFile) return 0; } - u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom; + //u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom; #ifndef NO_DEBUGGER if(CPUIsELF(szFile)) { @@ -1519,7 +1518,7 @@ int CPULoadRom(const char *szFile) } } else #endif //NO_DEBUGGER - if(szFile!=NULL) +/* if(szFile!=NULL) { if(!utilLoad(szFile, utilIsGBAImage, @@ -1538,7 +1537,7 @@ int CPULoadRom(const char *szFile) for(i = (romSize+1)&~1; i < 0x2000000; i+=2) { WRITE16LE(temp, (i >> 1) & 0xFFFF); temp++; - } + }*/ bios = (u8 *)calloc(1,0x4000); if(bios == NULL) { @@ -2201,7 +2200,7 @@ void CPUCompareVCOUNT() } if (layerEnableDelay>0) { - layerEnableDelay--; + --layerEnableDelay; if (layerEnableDelay==1) layerEnable = layerSettings & DISPCNT; } @@ -2233,7 +2232,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) while(c != 0) { CPUWriteMemory(d, 0); d += di; - c--; + --c; } } else { while(c != 0) { @@ -2241,7 +2240,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) CPUWriteMemory(d, cpuDmaLast); d += di; s += si; - c--; + --c; } } } else { @@ -2252,7 +2251,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) while(c != 0) { CPUWriteHalfWord(d, 0); d += di; - c--; + --c; } } else { while(c != 0) { @@ -2261,7 +2260,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) cpuDmaLast |= (cpuDmaLast<<16); d += di; s += si; - c--; + --c; } } } @@ -2521,7 +2520,6 @@ void CPUCheckDMA(int reason, int dmamask) doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, DM3CNT_L ? DM3CNT_L : 0x10000, DM3CNT_H & 0x0400); - if(DM3CNT_H & 0x4000) { IF |= 0x0800; UPDATE_REG(0x202, IF); @@ -2568,7 +2566,7 @@ void CPUUpdateRegister(u32 address, u16 value) windowOn = (layerEnable & 0x6000) ? true : false; if(change && !((value & 0x80))) { if(!(DISPSTAT & 1)) { - //lcdTicks = 1008; + lcdTicks = 1008; // VCOUNT = 0; // UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFC; @@ -2963,65 +2961,61 @@ void CPUUpdateRegister(u32 address, u16 value) timerOnOffDelay|=8; cpuNextEvent = cpuTotalTicks; break; - - -#ifndef NO_LINK - case COMM_SIOCNT: - StartLink(value); - break; - - case COMM_SIODATA8: - UPDATE_REG(COMM_SIODATA8, value); - break; + case 0x128: +#ifdef LINK_EMULATION + if (linkenable) + { + StartLink(value); + } + else #endif - + { + if(value & 0x80) { + value &= 0xff7f; + if(value & 1 && (value & 0x4000)) { + UPDATE_REG(0x12a, 0xFF); + IF |= 0x80; + UPDATE_REG(0x202, IF); + value &= 0x7f7f; + } + } + UPDATE_REG(0x128, value); + } + break; + case 0x12a: +#ifdef LINK_EMULATION + if(linkenable && lspeed) + LinkSSend(value); +#endif + { + UPDATE_REG(0x134, value); + } + break; case 0x130: - P1 |= (value & 0x3FF); - UPDATE_REG(0x130, P1); - break; - + P1 |= (value & 0x3FF); + UPDATE_REG(0x130, P1); + break; case 0x132: - UPDATE_REG(0x132, value & 0xC3FF); - break; - -#ifndef NO_LINK - case COMM_RCNT: - StartGPLink(value); - break; - - case COMM_JOYCNT: - { - u16 cur = READ16LE(&ioMem[COMM_JOYCNT]); - - if (value & JOYCNT_RESET) cur &= ~JOYCNT_RESET; - if (value & JOYCNT_RECV_COMPLETE) cur &= ~JOYCNT_RECV_COMPLETE; - if (value & JOYCNT_SEND_COMPLETE) cur &= ~JOYCNT_SEND_COMPLETE; - if (value & JOYCNT_INT_ENABLE) cur |= JOYCNT_INT_ENABLE; - - UPDATE_REG(COMM_JOYCNT, cur); - } - break; - - case COMM_JOY_RECV_L: - UPDATE_REG(COMM_JOY_RECV_L, value); - break; - case COMM_JOY_RECV_H: - UPDATE_REG(COMM_JOY_RECV_H, value); - break; - - case COMM_JOY_TRANS_L: - UPDATE_REG(COMM_JOY_TRANS_L, value); - UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) | JOYSTAT_SEND); - break; - case COMM_JOY_TRANS_H: - UPDATE_REG(COMM_JOY_TRANS_H, value); - break; - - case COMM_JOYSTAT: - UPDATE_REG(COMM_JOYSTAT, (READ16LE(&ioMem[COMM_JOYSTAT]) & 0xf) | (value & 0xf0)); - break; + UPDATE_REG(0x132, value & 0xC3FF); + break; + case 0x134: +#ifdef LINK_EMULATION + if (linkenable) + StartGPLink(value); + else #endif + UPDATE_REG(0x134, value); + break; + case 0x140: +#ifdef LINK_EMULATION + if (linkenable) + StartJOYLink(value); + else +#endif + UPDATE_REG(0x140, value); + + break; case 0x200: IE = value & 0x3FFF; UPDATE_REG(0x200, IE); @@ -3061,7 +3055,7 @@ void CPUUpdateRegister(u32 address, u16 value) for(int i = 8; i < 15; i++) { memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1; - memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1; + memoryWaitSeq32[i] = (memoryWaitSeq[i]<<1) + 1; } if((value & 0x4000) == 0x4000) { @@ -3173,7 +3167,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) saveType = 0; useBios = false; - if(useBiosFile) { +/* if(useBiosFile) { int size = 0x4000; if(utilLoad(biosFileName, CPUIsGBABios, @@ -3184,7 +3178,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) else systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BIOS file size")); } - } + }*/ if(!useBios) { memcpy(bios, myROM, sizeof(myROM)); @@ -3256,6 +3250,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) void CPUReset() { + systemCartridgeRumble(false); if(gbaSaveType == 0) { if(eepromInUse) gbaSaveType = 3; @@ -3552,7 +3547,7 @@ void CPUReset() cpuDmaHack = false; - lastTime = systemGetClock(); + //lastTime = systemGetClock(); SWITicks = 0; } @@ -3672,7 +3667,7 @@ void CPULoop(int ticks) // if in V-Blank mode, keep computing... if(DISPSTAT & 2) { lcdTicks += 1008; - VCOUNT++; + ++VCOUNT; UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFD; UPDATE_REG(0x04, DISPSTAT); @@ -3687,7 +3682,7 @@ void CPULoop(int ticks) } } - if(VCOUNT > 227) { //Reaching last line + if(VCOUNT >= 228) { //Reaching last line DISPSTAT &= 0xFFFC; UPDATE_REG(0x04, DISPSTAT); VCOUNT = 0; @@ -3701,26 +3696,26 @@ void CPULoop(int ticks) if(DISPSTAT & 2) { // if in H-Blank, leave it and move to drawing mode - VCOUNT++; + ++VCOUNT; UPDATE_REG(0x06, VCOUNT); lcdTicks += 1008; DISPSTAT &= 0xFFFD; if(VCOUNT == 160) { - count++; + ++count; systemFrame(); if((count % 10) == 0) { system10Frames(60); } if(count == 60) { - u32 time = systemGetClock(); + /*u32 time = systemGetClock(); if(time != lastTime) { u32 t = 100000/(time - lastTime); systemShowSpeed(t); } else systemShowSpeed(0); - lastTime = time; + lastTime = time;*/ count = 0; } u32 joy = 0; @@ -3729,7 +3724,7 @@ void CPULoop(int ticks) // read default joystick joy = systemReadJoypad(-1); P1 = 0x03FF ^ (joy & 0x3FF); - if(cpuEEPROMSensorEnabled) + //if(cpuEEPROMSensorEnabled) systemUpdateMotionSensor(); UPDATE_REG(0x130, P1); u16 P1CNT = READ16LE(((u16 *)&ioMem[0x132])); @@ -3759,7 +3754,7 @@ void CPULoop(int ticks) capture = (ext & 2) ? true : false; if(capture && !capturePrevious) { - captureNumber++; + ++captureNumber; systemScreenCapture(captureNumber); } capturePrevious = capture; @@ -3776,7 +3771,7 @@ void CPULoop(int ticks) systemDrawScreen(); frameCount = 0; } else - frameCount++; + ++frameCount; if(systemPauseOnFrame()) ticks = 0; } @@ -3791,8 +3786,8 @@ void CPULoop(int ticks) switch(systemColorDepth) { case 16: { - u16 *dest = (u16 *)pix + 242 * VCOUNT; - for(int x = 0; x < 240;) { + u16 *dest = (u16 *)pix + 242 * (VCOUNT+1); + for(u32 x = 0; x < 240u;) { *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; @@ -3819,8 +3814,8 @@ void CPULoop(int ticks) break; case 24: { - u8 *dest = (u8 *)pix + 240 * VCOUNT * 3; - for(int x = 0; x < 240;) { + u8 *dest = (u8 *)pix + VCOUNT * 720; + for(u32 x = 0; x < 240u;) { *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; dest += 3; *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; @@ -3861,8 +3856,8 @@ void CPULoop(int ticks) break; case 32: { - u32 *dest = (u32 *)pix + 241 * VCOUNT; - for(int x = 0; x < 240; ) { + u32 *dest = (u32 *)pix + 241 * (VCOUNT+1); + for(u32 x = 0; x < 240u; ) { *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; @@ -3928,7 +3923,7 @@ void CPULoop(int ticks) if(timer1On) { if(TM1CNT & 4) { if(timerOverflow & 1) { - TM1D++; + ++TM1D; if(TM1D == 0) { TM1D += timer1Reload; timerOverflow |= 2; @@ -3959,7 +3954,7 @@ void CPULoop(int ticks) if(timer2On) { if(TM2CNT & 4) { if(timerOverflow & 2) { - TM2D++; + ++TM2D; if(TM2D == 0) { TM2D += timer2Reload; timerOverflow |= 4; @@ -3988,7 +3983,7 @@ void CPULoop(int ticks) if(timer3On) { if(TM3CNT & 4) { if(timerOverflow & 4) { - TM3D++; + ++TM3D; if(TM3D == 0) { TM3D += timer3Reload; if(TM3CNT & 0x40) { @@ -4065,7 +4060,6 @@ void CPULoop(int ticks) if(gba_link_enabled) cpuNextEvent = 1; #endif - if(IF && (IME & 1) && armIrqEnable) { int res = IF & IE; if(stopState) @@ -4131,6 +4125,7 @@ void CPULoop(int ticks) } } + #ifdef TILED_RENDERING union u8h { @@ -4398,7 +4393,6 @@ void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line) } #endif - struct EmulatedSystem GBASystem = { // emuMain CPULoop, diff --git a/source/vba/gba/GBAcpu.h b/source/vba/gba/GBAcpu.h index 53fa2d3..e9fa051 100644 --- a/source/vba/gba/GBAcpu.h +++ b/source/vba/gba/GBAcpu.h @@ -5,11 +5,7 @@ extern int armExecute(); extern int thumbExecute(); #ifdef __GNUC__ -#ifndef __APPLE__ -# define INSN_REGPARM __attribute__((regparm(1))) -#else # define INSN_REGPARM /*nothing*/ -#endif # define LIKELY(x) __builtin_expect(!!(x),1) # define UNLIKELY(x) __builtin_expect(!!(x),0) #else diff --git a/source/vba/gba/GBAinline.h b/source/vba/gba/GBAinline.h index fe53a88..77289a1 100644 --- a/source/vba/gba/GBAinline.h +++ b/source/vba/gba/GBAinline.h @@ -6,8 +6,7 @@ #include "RTC.h" #include "Sound.h" #include "agbprint.h" -#include "GBAcpu.h" -#include "GBALink.h" +#include "vmmem.h" // Nintendo GC Virtual Memory extern const u32 objTilesAddress[3]; @@ -34,16 +33,83 @@ extern bool timer3On; extern int timer3Ticks; extern int timer3ClockReload; extern int cpuTotalTicks; +extern u32 RomIdCode; -#define CPUReadByteQuick(addr) \ +#define gid(a,b,c) (a|(b<<8)|(c<<16)) +#define CORVETTE gid('A','V','C') + +/***************************************************************************** + * Nintendo GC Virtual Memory function override + * Tantric September 2008 + ****************************************************************************/ + +#define CPUReadByteQuickDef(addr) \ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] -#define CPUReadHalfWordQuick(addr) \ +#define CPUReadHalfWordQuickDef(addr) \ READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) -#define CPUReadMemoryQuick(addr) \ +#define CPUReadMemoryQuickDef(addr) \ READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) +u8 inline CPUReadByteQuick( u32 addr ) +{ + switch(addr >> 24 ) + { + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: +#ifdef USE_VM + return VMRead8( addr & 0x1FFFFFF ); +#endif + default: + return CPUReadByteQuickDef(addr); + } + + return 0; +} + +u16 inline CPUReadHalfWordQuick( u32 addr ) +{ + switch(addr >> 24) + { + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: +#ifdef USE_VM + return VMRead16( addr & 0x1FFFFFF ); +#endif + default: + return CPUReadHalfWordQuickDef(addr); + } + + return 0; +} + +u32 inline CPUReadMemoryQuick( u32 addr ) +{ + switch(addr >> 24) + { + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: +#ifdef USE_VM + return VMRead32( addr & 0x1FFFFFF ); +#endif + default: + return CPUReadMemoryQuickDef(addr); + } + + return 0; +} + +/***************************************************************************** + * End of VM override + ****************************************************************************/ + static inline u32 CPUReadMemory(u32 address) { u32 value; @@ -80,8 +146,8 @@ static inline u32 CPUReadMemory(u32 address) if((address < 0x4000400) && ioReadable[address & 0x3fc]) { if(ioReadable[(address & 0x3fc) + 2]) { value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); - if ((address & 0x3fc) == COMM_JOY_RECV_L) - UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV); + //if ((address & 0x3fc) == COMM_JOY_RECV_L) + // UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV); } else { value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); } @@ -96,8 +162,8 @@ static inline u32 CPUReadMemory(u32 address) address = (address & 0x1fffc); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { - value = 0; - break; + value = 0; + break; } if ((address & 0x18000) == 0x18000) address &= 0x17fff; @@ -107,39 +173,68 @@ static inline u32 CPUReadMemory(u32 address) value = READ32LE(((u32 *)&oam[address & 0x3FC])); break; case 8: + // Must be cartridge ROM, reading other sensors doesn't allow 32-bit access. case 9: case 10: case 11: case 12: - value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); +#ifdef USE_VM // Nintendo GC Virtual Memory + value = VMRead32( address & 0x1FFFFFC ); +#else + value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); +#endif break; case 13: value = eepromRead(address); break; case 14: case 15: - value = flashRead(address) * 0x01010101; - break; + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + value = flashRead(address) * 0x01010101; + break; // default default: -unreadable: + unreadable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + armNextPC - 4 : armNextPC - 2); } #endif - if(cpuDmaHack) { - value = cpuDmaLast; - } else { + + if(cpuDmaHack) { + value = cpuDmaLast; + } else { if(armState) { - return CPUReadMemoryQuick(reg[15].I); +#ifdef USE_VM // Nintendo GC Virtual Memory + return CPUReadMemoryQuick(reg[15].I); +#else + return CPUReadMemoryQuickDef(reg[15].I); +#endif } else { - return CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; +#ifdef USE_VM // Nintendo GC Virtual Memory + return CPUReadHalfWordQuick(reg[15].I) | + CPUReadHalfWordQuick(reg[15].I) << 16; +#else + return CPUReadHalfWordQuickDef(reg[15].I) | + CPUReadHalfWordQuickDef(reg[15].I) << 16; +#endif } - } - break; + } + break; } if(oldAddress & 3) { @@ -216,14 +311,14 @@ static inline u32 CPUReadHalfWord(u32 address) if (((address & 0x3fe) == 0x100) && timer0On) value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); else - if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) - value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); - else - if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) - value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); - else - if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) - value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); + if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) + value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); + else + if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) + value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); + else + if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) + value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); } } else if((address < 0x4000400) && ioReadable[address & 0x3fc]) @@ -239,8 +334,8 @@ static inline u32 CPUReadHalfWord(u32 address) address = (address & 0x1fffe); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { - value = 0; - break; + value = 0; + break; } if ((address & 0x18000) == 0x18000) address &= 0x17fff; @@ -250,34 +345,66 @@ static inline u32 CPUReadHalfWord(u32 address) value = READ16LE(((u16 *)&oam[address & 0x3fe])); break; case 8: + // Use existing case statement and faster test for potential speed improvement + // This is possibly the GPIO port that controls the real time clock, + // WarioWare Twisted! tilt sensors, rumble, and solar sensors. + if(address >= 0x80000c4 && address <= 0x80000c8) { + // this function still works if there is no real time clock + // and does a normal memory read in that case. + value = rtcRead(address & 0xFFFFFFE); + break; + } case 9: case 10: case 11: case 12: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) - value = rtcRead(address); - else - value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); +#ifdef USE_VM // Nintendo GC Virtual Memory + value = VMRead16( address & 0x1FFFFFE ); +#else + value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); +#endif break; case 13: value = eepromRead(address); break; case 14: case 15: - value = flashRead(address) * 0x0101; + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + value = flashRead(address) * 0x0101; break; // default default: -unreadable: - if(cpuDmaHack) { - value = cpuDmaLast & 0xFFFF; - } else { - if(armState) { - value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); - } else { - value = CPUReadHalfWordQuick(reg[15].I); - } - } + unreadable: + if(cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; + } else { + if(armState) { +#ifdef USE_VM // Nintendo GC Virtual Memory + value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); +#else + value = CPUReadHalfWordQuickDef(reg[15].I + (address & 2)); +#endif + } else { +#ifdef USE_VM // Nintendo GC Virtual Memory + value = CPUReadHalfWordQuick(reg[15].I); +#else + value = CPUReadHalfWordQuickDef(reg[15].I); +#endif + } + } #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { log("Illegal halfword read: %08x at %08x (%08x)\n", oldAddress, reg[15].I, value); @@ -343,55 +470,71 @@ static inline u8 CPUReadByte(u32 address) case 6: address = (address & 0x1ffff); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return 0; + return 0; if ((address & 0x18000) == 0x18000) address &= 0x17fff; return vram[address]; case 7: return oam[address & 0x3ff]; case 8: + // the real time clock doesn't support byte reads, so don't bother checking for it. case 9: case 10: case 11: case 12: +#ifdef USE_VM // Nintendo GC Virtual Memory + return VMRead8( address & 0x1FFFFFF ); +#else return rom[address & 0x1FFFFFF]; +#endif case 13: return eepromRead(address); case 14: case 15: { - if (cpuEEPROMSensorEnabled) { - switch (address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8) | 0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - return flashRead(address); + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + return flashRead(address); } // default default: -unreadable: + unreadable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + armNextPC - 4 : armNextPC - 2); } #endif - if(cpuDmaHack) { - return cpuDmaLast & 0xFF; - } else { - if(armState) { - return CPUReadByteQuick(reg[15].I + (address & 3)); - } else { - return CPUReadByteQuick(reg[15].I + (address & 1)); - } - } + if(cpuDmaHack) { + return cpuDmaLast & 0xFF; + } else { + if(armState) { +#ifdef USE_VM // Nintendo GC Virtual Memory + return CPUReadByteQuick(reg[15].I+(address & 3)); +#else + return CPUReadByteQuickDef(reg[15].I+(address & 3)); +#endif + } else { +#ifdef USE_VM // Nintendo GC Virtual Memory + return CPUReadByteQuick(reg[15].I+(address & 1)); +#else + return CPUReadByteQuickDef(reg[15].I+(address & 1)); +#endif + } + } + break; } } @@ -402,9 +545,9 @@ static inline void CPUWriteMemory(u32 address, u32 value) if(address & 3) { if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { log("Unaligned word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); } } #endif @@ -416,7 +559,7 @@ static inline void CPUWriteMemory(u32 address, u32 value) #ifdef BKPT_SUPPORT if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) cheatsWriteMemory(address & 0x203FFFC, - value); + value); else #endif WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); @@ -425,7 +568,7 @@ static inline void CPUWriteMemory(u32 address, u32 value) #ifdef BKPT_SUPPORT if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) cheatsWriteMemory(address & 0x3007FFC, - value); + value); else #endif WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); @@ -440,9 +583,10 @@ static inline void CPUWriteMemory(u32 address, u32 value) #ifdef BKPT_SUPPORT if(*((u32 *)&freezePRAM[address & 0x3fc])) cheatsWriteMemory(address & 0x70003FC, - value); + value); else #endif + if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE) WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); break; case 0x06: @@ -542,6 +686,7 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) value); else #endif + if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE) WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value); break; case 6: diff --git a/source/vba/gba/Mode0.cpp b/source/vba/gba/Mode0.cpp index c0d5812..dfa6682 100644 --- a/source/vba/gba/Mode0.cpp +++ b/source/vba/gba/Mode0.cpp @@ -1,3 +1,11 @@ +/* +Mode 0 is the tiled graphics mode, with all the layers available. +There is no rotation or scaling in this mode. +It can be either 16 colours (with 16 different palettes) or 256 colors. +There are 1024 tiles available. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" @@ -7,9 +15,18 @@ void mode0RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); return; } @@ -38,11 +55,55 @@ void mode0RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(u32 x = 0; x < 240u; ++x) { u32 color = backdrop; u8 top = 0x20; - - if(line0[x] < color) { + //--DCN + // + // !NON-PORTABLE!!NON-PORTABLE! + // + // This takes advantage of the fact that the Wii has far more registers + // (32 vs 8) than IA-32 based processors processors (Intel, AMD). + // This actually runs SLOWER on those. This code will only show + // improvements on a PowerPC machine! (19.5% improvement: isolated tests) + //* + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li2 < li1) ? (li2) : (li1); + + if(li3 < r) { + r = (li4 < li3) ? (li4) : (li3); + }else if(li4 < r){ + r = (li4); + } + + if(line0[x] < backdrop) { + color = line0[x]; + top = 0x01; + } + + if(r < (u8)(color >> 24)) { + if(r == li1){ + color = line1[x]; + top = 0x02; + }else if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li3){ + color = line3[x]; + top = 0x08; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } + + //Original + /* + if(line0[x] < color) { color = line0[x]; top = 0x01; } @@ -56,41 +117,49 @@ void mode0RenderLine() color = line2[x]; top = 0x04; } - - if((u8)(line3[x]>>24) < (u8)(color >> 24)) { + if((u8)(line3[x]>>24) < (u8)(color >> 24)) { color = line3[x]; top = 0x08; } - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { color = lineOBJ[x]; top = 0x10; } + //*/ if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line0[x]>>24) < (u8)(back >> 24)) { - back = line0[x]; - top2 = 0x01; - } - - if((u8)(line1[x]>>24) < (u8)(back >> 24)) { - back = line1[x]; - top2 = 0x02; - } - - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } - - if((u8)(line3[x]>>24) < (u8)(back >> 24)) { - back = line3[x]; - top2 = 0x08; - } + u8 li0 = (u8)(line0[x]>>24); + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + + u8 r = (li1 < li0) ? (li1) : (li0); + + if(li2 < r) { + r = (li3 < li2) ? (li3) : (li2); + }else if(li3 < r){ + r = (li3); + } + + if(r < (u8)(color >> 24)) { + if(r == li0){ + back = line0[x]; + top2 = 0x01; + }else if(r == li1){ + back = line1[x]; + top2 = 0x02; + }else if(r == li2){ + back = line2[x]; + top2 = 0x04; + }else if(r == li3){ + back = line3[x]; + top2 = 0x08; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -119,9 +188,20 @@ void mode0RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + return; } @@ -154,32 +234,41 @@ void mode0RenderLineNoWindow() for(int x = 0; x < 240; x++) { u32 color = backdrop; - u8 top = 0x20; + u8 top = 0x20; - if(line0[x] < color) { - color = line0[x]; - top = 0x01; - } - - if(line1[x] < (color & 0xFF000000)) { - color = line1[x]; - top = 0x02; - } - - if(line2[x] < (color & 0xFF000000)) { - color = line2[x]; - top = 0x04; - } - - if(line3[x] < (color & 0xFF000000)) { - color = line3[x]; - top = 0x08; - } - - if(lineOBJ[x] < (color & 0xFF000000)) { - color = lineOBJ[x]; - top = 0x10; - } + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li2 < li1) ? (li2) : (li1); + + if(li3 < r) { + r = (li4 < li3) ? (li4) : (li3); + }else if(li4 < r){ + r = (li4); + } + + if(line0[x] < backdrop) { + color = line0[x]; + top = 0x01; + } + + if(r < (u8)(color >> 24)) { + if(r == li1){ + color = line1[x]; + top = 0x02; + }else if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li3){ + color = line3[x]; + top = 0x08; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } if(!(color & 0x00010000)) { switch(effect) { @@ -189,40 +278,30 @@ void mode0RenderLineNoWindow() { if(top & BLDMOD) { u32 back = backdrop; - u8 top2 = 0x20; - if(line0[x] < back) { - if(top != 0x01) { + u8 top2 = 0x20; + + if((top != 0x01) && line0[x] < back) { back = line0[x]; top2 = 0x01; - } } - - if(line1[x] < (back & 0xFF000000)) { - if(top != 0x02) { + if((top != 0x02) && line1[x] < (back & 0xFF000000)) { back = line1[x]; top2 = 0x02; - } } - if(line2[x] < (back & 0xFF000000)) { - if(top != 0x04) { + if((top != 0x04) && line2[x] < (back & 0xFF000000)) { back = line2[x]; top2 = 0x04; - } } - if(line3[x] < (back & 0xFF000000)) { - if(top != 0x08) { + if((top != 0x08) && line3[x] < (back & 0xFF000000)) { back = line3[x]; top2 = 0x08; - } } - if(lineOBJ[x] < (back & 0xFF000000)) { - if(top != 0x10) { + if((top != 0x10) && lineOBJ[x] < (back & 0xFF000000)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) @@ -245,27 +324,45 @@ void mode0RenderLineNoWindow() } else { // semi-transparent OBJ u32 back = backdrop; - u8 top2 = 0x20; + u8 top2 = 0x20; - if(line0[x] < back) { - back = line0[x]; - top2 = 0x01; - } - - if(line1[x] < (back & 0xFF000000)) { - back = line1[x]; - top2 = 0x02; - } - - if(line2[x] < (back & 0xFF000000)) { - back = line2[x]; - top2 = 0x04; - } - - if(line3[x] < (back & 0xFF000000)) { - back = line3[x]; - top2 = 0x08; - } + //--DCN + // This is pretty much the exact same result: + // line1[x] < (back & 0xFF000000) + // + // (u8)(line0[x]>>24) < (u8)(back >> 24) + // + // The only difference is that the first is stored in a u32, + // and the second is stored in a u8 + //* + u8 li0 = (u8)(line0[x]>>24); + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + + u8 r = (li1 < li0) ? (li1) : (li0); + + if(li2 < r) { + r = (li3 < li2) ? (li3) : (li2); + }else if(li3 < r){ + r = (li3); + } + + if(r < (u8)(color >> 24)) { + if(r == li0){ + back = line0[x]; + top2 = 0x01; + }else if(r == li1){ + back = line1[x]; + top2 = 0x02; + }else if(r == li2){ + back = line2[x]; + top2 = 0x04; + }else if(r == li3){ + back = line3[x]; + top2 = 0x08; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -294,9 +391,20 @@ void mode0RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + return; } @@ -372,7 +480,7 @@ void mode0RenderLineAll() } } - if((mask & 1) && (line0[x] < color)) { + if((mask & 1) && (line0[x] < color)) { color = line0[x]; top = 0x01; } @@ -448,39 +556,30 @@ void mode0RenderLineAll() if(top & BLDMOD) { u32 back = backdrop; u8 top2 = 0x20; - if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { - if(top != 0x01) { + + if((mask & 1) && (top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { back = line0[x]; top2 = 0x01; - } } - if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { - if(top != 0x02) { + if((mask & 2) && (top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { back = line1[x]; top2 = 0x02; - } } - if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { back = line2[x]; top2 = 0x04; - } } - if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { - if(top != 0x08) { + if((mask & 8) && (top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { back = line3[x]; top2 = 0x08; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode1.cpp b/source/vba/gba/Mode1.cpp index 4cc3b07..814b474 100644 --- a/source/vba/gba/Mode1.cpp +++ b/source/vba/gba/Mode1.cpp @@ -1,3 +1,12 @@ +/* +Mode 1 is a tiled graphics mode, but with background layer 2 supporting scaling and rotation. +There is no layer 3 in this mode. +Layers 0 and 1 can be either 16 colours (with 16 different palettes) or 256 colours. +There are 1024 tiles available. +Layer 2 is 256 colours and allows only 256 tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" @@ -7,9 +16,20 @@ void mode1RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -40,49 +60,64 @@ void mode1RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(u32 x = 0; x < 240u; ++x) { u32 color = backdrop; u8 top = 0x20; - if(line0[x] < color) { - color = line0[x]; - top = 0x01; - } - - if((u8)(line1[x]>>24) < (u8)(color >> 24)) { - color = line1[x]; - top = 0x02; - } - - if((u8)(line2[x]>>24) < (u8)(color >> 24)) { - color = line2[x]; - top = 0x04; - } - - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { - color = lineOBJ[x]; - top = 0x10; - } + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li2 < li1) ? (li2) : (li1); + + if(li4 < r){ + r = (li4); + } + + if(line0[x] < backdrop) { + color = line0[x]; + top = 0x01; + } + + if(r < (u8)(color >> 24)) { + if(r == li1){ + color = line1[x]; + top = 0x02; + }else if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line0[x]>>24) < (u8)(back >> 24)) { - back = line0[x]; - top2 = 0x01; - } - - if((u8)(line1[x]>>24) < (u8)(back >> 24)) { - back = line1[x]; - top2 = 0x02; - } - - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } + u8 li0 = (u8)(line0[x]>>24); + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 r = (li1 < li0) ? (li1) : (li0); + + if(li2 < r) { + r = (li2); + } + + if(r < (u8)(back >> 24)) { + if(r == li0){ + back = line0[x]; + top2 = 0x01; + }else if(r == li1){ + back = line1[x]; + top2 = 0x02; + }else if(r == li2){ + back = line2[x]; + top2 = 0x04; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -113,9 +148,20 @@ void mode1RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -147,29 +193,37 @@ void mode1RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; - if(line0[x] < color) { - color = line0[x]; - top = 0x01; - } - - if((u8)(line1[x]>>24) < (u8)(color >> 24)) { - color = line1[x]; - top = 0x02; - } - - if((u8)(line2[x]>>24) < (u8)(color >> 24)) { - color = line2[x]; - top = 0x04; - } - - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { - color = lineOBJ[x]; - top = 0x10; - } + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li2 < li1) ? (li2) : (li1); + + if(li4 < r){ + r = (li4); + } + + if(line0[x] < backdrop) { + color = line0[x]; + top = 0x01; + } + + if(r < (u8)(color >> 24)) { + if(r == li1){ + color = line1[x]; + top = 0x02; + }else if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } if(!(color & 0x00010000)) { switch((BLDMOD >> 6) & 3) { @@ -180,33 +234,26 @@ void mode1RenderLineNoWindow() if(top & BLDMOD) { u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line0[x]>>24) < (u8)(back >> 24)) { - if(top != 0x01) { - back = line0[x]; - top2 = 0x01; - } - } - if((u8)(line1[x]>>24) < (u8)(back >> 24)) { - if(top != 0x02) { - back = line1[x]; - top2 = 0x02; - } - } + if((top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { + back = line0[x]; + top2 = 0x01; + } - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - if(top != 0x04) { - back = line2[x]; - top2 = 0x04; - } - } + if((top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { + back = line1[x]; + top2 = 0x02; + } - if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { - back = lineOBJ[x]; - top2 = 0x10; - } - } + if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } + + if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { + back = lineOBJ[x]; + top2 = 0x10; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -225,24 +272,32 @@ void mode1RenderLineNoWindow() break; } } else { - // semi-transparent OBJ - u32 back = backdrop; - u8 top2 = 0x20; + // semi-transparent OBJ + u32 back = backdrop; + u8 top2 = 0x20; - if((u8)(line0[x]>>24) < (u8)(back >> 24)) { - back = line0[x]; - top2 = 0x01; - } - - if((u8)(line1[x]>>24) < (u8)(back >> 24)) { - back = line1[x]; - top2 = 0x02; - } - - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } + u8 li0 = (u8)(line0[x]>>24); + u8 li1 = (u8)(line1[x]>>24); + u8 li2 = (u8)(line2[x]>>24); + + u8 r = (li1 < li0) ? (li1) : (li0); + + if(li2 < r) { + r = (li2); + } + + if(r < (u8)(back >> 24)) { + if(r == li0){ + back = line0[x]; + top2 = 0x01; + }else if(r == li1){ + back = line1[x]; + top2 = 0x02; + }else if(r == li2){ + back = line2[x]; + top2 = 0x04; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -273,9 +328,20 @@ void mode1RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -333,7 +399,7 @@ void mode1RenderLineAll() u8 inWin1Mask = WININ >> 8; u8 outMask = WINOUT & 0xFF; - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; u8 mask = outMask; @@ -353,22 +419,23 @@ void mode1RenderLineAll() } } - if(line0[x] < color && (mask & 1)) { + // At the very least, move the inexpensive 'mask' operation up front + if((mask & 1) && line0[x] < backdrop) { color = line0[x]; top = 0x01; } - if((u8)(line1[x]>>24) < (u8)(color >> 24) && (mask & 2)) { + if((mask & 2) && (u8)(line1[x]>>24) < (u8)(color >> 24)) { color = line1[x]; top = 0x02; } - if((u8)(line2[x]>>24) < (u8)(color >> 24) && (mask & 4)) { + if((mask & 4) && (u8)(line2[x]>>24) < (u8)(color >> 24)) { color = line2[x]; top = 0x04; } - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16)) { + if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { color = lineOBJ[x]; top = 0x10; } @@ -378,7 +445,7 @@ void mode1RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { + if((mask & 1) && (u8)(line0[x]>>24) < (u8)(backdrop >> 24)) { back = line0[x]; top2 = 0x01; } @@ -420,32 +487,24 @@ void mode1RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { - if(top != 0x01) { + if((mask & 1) && (top != 0x01) && (u8)(line0[x]>>24) < (u8)(backdrop >> 24)) { back = line0[x]; top2 = 0x01; - } } - if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { - if(top != 0x02) { + if((mask & 2) && (top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { back = line1[x]; top2 = 0x02; - } } - if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { back = line2[x]; top2 = 0x04; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode2.cpp b/source/vba/gba/Mode2.cpp index 527a1ff..d61b0c3 100644 --- a/source/vba/gba/Mode2.cpp +++ b/source/vba/gba/Mode2.cpp @@ -1,3 +1,11 @@ +/* +Mode 2 is a 256 colour tiled graphics mode which supports scaling and rotation. +There is no background layer 0 or 1 in this mode. Only background layers 2 and 3. +There are 256 tiles available. +It does not support flipping. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" @@ -7,9 +15,20 @@ void mode2RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -43,40 +62,51 @@ void mode2RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; - - if((u8)(line2[x]>>24) < (u8)(color >> 24)) { - color = line2[x]; - top = 0x04; - } - - if((u8)(line3[x]>>24) < (u8)(color >> 24)) { - color = line3[x]; - top = 0x08; - } - - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { - color = lineOBJ[x]; - top = 0x10; - } + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li3 < li2) ? (li3) : (li2); + + if(li4 < r){ + r = (li4); + } + + if(r < (u8)(color >> 24)) { + if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li3){ + color = line3[x]; + top = 0x08; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } - - if((u8)(line3[x]>>24) < (u8)(back >> 24)) { - back = line3[x]; - top2 = 0x08; - } + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 r = (li3 < li2) ? (li3) : (li2); + + if(r < (u8)(back >> 24)) { + if(r == li2){ + back = line2[x]; + top2 = 0x04; + }else if(r == li3){ + back = line3[x]; + top2 = 0x08; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -108,9 +138,20 @@ void mode2RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -144,25 +185,32 @@ void mode2RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; - - if((u8)(line2[x]>>24) < (u8)(color >> 24)) { - color = line2[x]; - top = 0x04; - } - - if((u8)(line3[x]>>24) < (u8)(color >> 24)) { - color = line3[x]; - top = 0x08; - } - - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { - color = lineOBJ[x]; - top = 0x10; - } + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 li4 = (u8)(lineOBJ[x]>>24); + + u8 r = (li3 < li2) ? (li3) : (li2); + + if(li4 < r){ + r = (li4); + } + + if(r < (u8)(color >> 24)) { + if(r == li2){ + color = line2[x]; + top = 0x04; + }else if(r == li3){ + color = line3[x]; + top = 0x08; + }else if(r == li4){ + color = lineOBJ[x]; + top = 0x10; + } + } if(!(color & 0x00010000)) { switch((BLDMOD >> 6) & 3) { @@ -174,26 +222,20 @@ void mode2RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - if(top != 0x04) { - back = line2[x]; - top2 = 0x04; - } + if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; } - if((u8)(line3[x]>>24) < (u8)(back >> 24)) { - if(top != 0x08) { - back = line3[x]; - top2 = 0x08; - } - } + if((top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { + back = line3[x]; + top2 = 0x08; + } - if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { - back = lineOBJ[x]; - top2 = 0x10; - } - } + if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { + back = lineOBJ[x]; + top2 = 0x10; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -216,15 +258,19 @@ void mode2RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - if((u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } - - if((u8)(line3[x]>>24) < (u8)(back >> 24)) { - back = line3[x]; - top2 = 0x08; - } + u8 li2 = (u8)(line2[x]>>24); + u8 li3 = (u8)(line3[x]>>24); + u8 r = (li3 < li2) ? (li3) : (li2); + + if(r < (u8)(back >> 24)) { + if(r == li2){ + back = line2[x]; + top2 = 0x04; + }else if(r == li3){ + back = line3[x]; + top2 = 0x08; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -256,9 +302,20 @@ void mode2RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -339,17 +396,17 @@ void mode2RenderLineAll() } } - if(line2[x] < color && (mask & 4)) { + if((mask & 4) && line2[x] < color) { color = line2[x]; top = 0x04; } - if((u8)(line3[x]>>24) < (u8)(color >> 24) && (mask & 8)) { + if((mask & 8) && (u8)(line3[x]>>24) < (u8)(color >> 24)) { color = line3[x]; top = 0x08; } - if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16)) { + if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { color = lineOBJ[x]; top = 0x10; } @@ -396,25 +453,19 @@ void mode2RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 4) && line2[x] < back) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && line2[x] < back) { back = line2[x]; top2 = 0x04; - } } - if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { - if(top != 0x08) { + if((mask & 8) && (top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { back = line3[x]; top2 = 0x08; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode3.cpp b/source/vba/gba/Mode3.cpp index 1b1d0c6..2d97265 100644 --- a/source/vba/gba/Mode3.cpp +++ b/source/vba/gba/Mode3.cpp @@ -1,3 +1,10 @@ +/* +Mode 3 is a 15-bit (32768) colour bitmap graphics mode. +It has a single layer, background layer 2, the same size as the screen. +It doesn't support paging, scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" @@ -7,9 +14,20 @@ void mode3RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -36,7 +54,7 @@ void mode3RenderLine() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; @@ -55,7 +73,7 @@ void mode3RenderLine() u32 back = background; u8 top2 = 0x20; - if(line2[x] < back) { + if(line2[x] < background) { back = line2[x]; top2 = 0x04; } @@ -89,9 +107,20 @@ void mode3RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -118,11 +147,11 @@ void mode3RenderLineNoWindow() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; - if(line2[x] < color) { + if(line2[x] < background) { color = line2[x]; top = 0x04; } @@ -142,18 +171,14 @@ void mode3RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if(line2[x] < back) { - if(top != 0x04) { - back = line2[x]; - top2 = 0x04; - } + if(top != 0x04 && (line2[x] < background) ) { + back = line2[x]; + top2 = 0x04; } - if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { - back = lineOBJ[x]; - top2 = 0x10; - } + if(top != 0x10 && ((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))) { + back = lineOBJ[x]; + top2 = 0x10; } if(top2 & (BLDMOD>>8)) @@ -178,7 +203,7 @@ void mode3RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if(line2[x] < back) { + if(line2[x] < background) { back = line2[x]; top2 = 0x04; } @@ -212,9 +237,20 @@ void mode3RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -268,7 +304,7 @@ void mode3RenderLineAll() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; u8 mask = outMask; @@ -288,7 +324,7 @@ void mode3RenderLineAll() } } - if((mask & 4) && (line2[x] < color)) { + if((mask & 4) && line2[x] < background) { color = line2[x]; top = 0x04; } @@ -303,7 +339,7 @@ void mode3RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && line2[x] < back) { + if((mask & 4) && line2[x] < background) { back = line2[x]; top2 = 0x04; } @@ -334,25 +370,20 @@ void mode3RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && line2[x] < back) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && line2[x] < back) { back = line2[x]; top2 = 0x04; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } } break; diff --git a/source/vba/gba/Mode4.cpp b/source/vba/gba/Mode4.cpp index 1907948..218f929 100644 --- a/source/vba/gba/Mode4.cpp +++ b/source/vba/gba/Mode4.cpp @@ -1,3 +1,10 @@ +/* +Mode 4 is a 256 colour bitmap graphics mode with 2 swappable pages. +It has a single layer, background layer 2, the same size as the screen. +It doesn't support scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "GBAGfx.h" #include "Globals.h" @@ -7,9 +14,20 @@ void mode4RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -35,11 +53,11 @@ void mode4RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; - if(line2[x] < color) { + if(line2[x] < backdrop) { color = line2[x]; top = 0x04; } @@ -54,7 +72,7 @@ void mode4RenderLine() u32 back = backdrop; u8 top2 = 0x20; - if(line2[x] < back) { + if(line2[x] < backdrop) { back = line2[x]; top2 = 0x04; } @@ -88,9 +106,20 @@ void mode4RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -116,11 +145,11 @@ void mode4RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; - if(line2[x] < color) { + if(line2[x] < backdrop) { color = line2[x]; top = 0x04; } @@ -140,18 +169,14 @@ void mode4RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - if(line2[x] < back) { - if(top != 0x04) { + if((top != 0x04) && line2[x] < backdrop) { back = line2[x]; top2 = 0x04; - } } - if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) @@ -210,9 +235,20 @@ void mode4RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -265,7 +301,7 @@ void mode4RenderLineAll() u8 inWin1Mask = WININ >> 8; u8 outMask = WINOUT & 0xFF; - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = backdrop; u8 top = 0x20; u8 mask = outMask; @@ -285,7 +321,7 @@ void mode4RenderLineAll() } } - if((mask & 4) && (line2[x] < color)) { + if((mask & 4) && (line2[x] < backdrop)) { color = line2[x]; top = 0x04; } @@ -331,25 +367,20 @@ void mode4RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 4) && line2[x] < back) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && (line2[x] < backdrop)) { back = line2[x]; top2 = 0x04; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } } break; diff --git a/source/vba/gba/Mode5.cpp b/source/vba/gba/Mode5.cpp index dc72427..17ddf55 100644 --- a/source/vba/gba/Mode5.cpp +++ b/source/vba/gba/Mode5.cpp @@ -1,3 +1,11 @@ +/* +Mode 5 is a low resolution (160x128) 15-bit colour bitmap graphics mode +with 2 swappable pages! +It has a single layer, background layer 2, lower resolution than the screen. +It doesn't support scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" @@ -5,9 +13,20 @@ void mode5RenderLine() { if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -36,11 +55,11 @@ void mode5RenderLine() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; - if(line2[x] < color) { + if(line2[x] < background) { color = line2[x]; top = 0x04; } @@ -87,9 +106,20 @@ void mode5RenderLine() void mode5RenderLineNoWindow() { if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); + gfxLastVCOUNT = VCOUNT; return; } @@ -118,11 +148,11 @@ void mode5RenderLineNoWindow() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; - if(line2[x] < color) { + if(line2[x] < background) { color = line2[x]; top = 0x04; } @@ -142,18 +172,14 @@ void mode5RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if(line2[x] < back) { - if(top != 0x04) { + if((top != 0x04) && line2[x] < background) { back = line2[x]; top2 = 0x04; - } } - if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) @@ -210,9 +236,19 @@ void mode5RenderLineNoWindow() void mode5RenderLineAll() { if(DISPCNT & 0x0080) { - for(int x = 0; x < 240; x++) { - lineMix[x] = 0x7fff; - } + + int x = 232; //240 - 8 + do{ + lineMix[x ] = + lineMix[x+1] = + lineMix[x+2] = + lineMix[x+3] = + lineMix[x+4] = + lineMix[x+5] = + lineMix[x+6] = + lineMix[x+7] = 0x7fff; + x-=8; + }while(x>=0); gfxLastVCOUNT = VCOUNT; return; } @@ -268,7 +304,7 @@ void mode5RenderLineAll() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; x++) { + for(int x = 0; x < 240; ++x) { u32 color = background; u8 top = 0x20; u8 mask = outMask; @@ -288,7 +324,7 @@ void mode5RenderLineAll() } } - if((mask & 4) && (line2[x] < color)) { + if((mask & 4) && (line2[x] < background)) { color = line2[x]; top = 0x04; } @@ -334,18 +370,14 @@ void mode5RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && line2[x] < back) { - if(top != 0x04) { + if((mask & 4) && (top != 0x04) && (line2[x] < background)) { back = line2[x]; top2 = 0x04; - } } - if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - if(top != 0x10) { + if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { back = lineOBJ[x]; top2 = 0x10; - } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/RTC.cpp b/source/vba/gba/RTC.cpp index 511bb47..82ad063 100644 --- a/source/vba/gba/RTC.cpp +++ b/source/vba/gba/RTC.cpp @@ -9,9 +9,6 @@ #include #include -// Defined in VGA-GX input.cpp -void systemCartridgeRumble(bool); - enum RTCSTATE { IDLE = 0, diff --git a/source/vba/gba/Sound.cpp b/source/vba/gba/Sound.cpp index 3c630b0..f111992 100644 --- a/source/vba/gba/Sound.cpp +++ b/source/vba/gba/Sound.cpp @@ -50,8 +50,8 @@ int soundTicks = SOUND_CLOCK_TICKS_; static float soundVolume = 1.0f; static int soundEnableFlag = 0x3ff; // emulator channels enabled -static float soundFiltering_ = -1; -static float soundVolume_ = -1; +static float soundFiltering_ = -1.0f; +static float soundVolume_ = -1.0f; void interp_rate() { /* empty for now */ } @@ -82,8 +82,8 @@ public: int readIndex; int count; int writeIndex; - u8 fifo [32]; int dac; + u8 fifo [32]; private: int timer; @@ -115,7 +115,7 @@ void Gba_Pcm::apply_control( int idx ) int ch = 0; if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) ) - ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3; + ch = ioMem [SGCNT0_H+1] >> (idx <<2) & 3; Blip_Buffer* out = 0; switch ( ch ) @@ -162,11 +162,10 @@ void Gba_Pcm::update( int dac ) int filter = 0; if ( soundInterpolation ) { - // base filtering on how long since last sample was output - int period = time - last_time; + unsigned period = unsigned(time - last_time); + unsigned idx = period >> 9; - int idx = (unsigned) period / 512; - if ( idx >= 3 ) + if ( idx > 3 ) idx = 3; static int const filters [4] = { 0, 0, 1, 2 }; @@ -204,7 +203,7 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer ) } // Read next sample from FIFO - count--; + --count; dac = fifo [readIndex]; readIndex = (readIndex + 1) & 31; pcm.update( dac ); @@ -284,14 +283,17 @@ static void apply_volume( bool apu_only = false ) if ( gb_apu ) { - static float const apu_vols [4] = { 0.25, 0.5, 1, 0.25 }; + static float const apu_vols [4] = { 0.25f, 0.5f, 1.0f, 0.25f }; gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] ); } if ( !apu_only ) { - for ( int i = 0; i < 3; i++ ) - pcm_synth [i].volume( 0.66 / 256 * soundVolume_ ); + double tmpVol = 0.002578125 * soundVolume_; // 0.66 / 256 * soundVolume_ + + pcm_synth[0].volume( tmpVol ); + pcm_synth[1].volume( tmpVol ); + pcm_synth[2].volume( tmpVol ); } } @@ -352,19 +354,14 @@ static void end_frame( blip_time_t time ) void flush_samples(Multi_Buffer * buffer) { -#ifdef __LIBRETRO__ - int numSamples = buffer->read_samples( (blip_sample_t*) soundFinalWave, buffer->samples_avail() ); - soundDriver->write(soundFinalWave, numSamples); - systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples); -#else // We want to write the data frame by frame to support legacy audio drivers // that don't use the length parameter of the write method. // TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the // samples at once to help reducing the audio delay on all platforms. - int soundBufferLen = ( soundSampleRate / 60 ) * 4; + int soundBufferLen = ( soundSampleRate / 60 ) << 2; // soundBufferLen should have a whole number of sample pairs - assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 ); + assert( soundBufferLen % ((sizeof *soundFinalWave)<<1) == 0 ); // number of samples in output buffer int const out_buf_size = soundBufferLen / sizeof *soundFinalWave; @@ -379,15 +376,16 @@ void flush_samples(Multi_Buffer * buffer) soundDriver->write(soundFinalWave, soundBufferLen); systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen); } -#endif } static void apply_filtering() { soundFiltering_ = soundFiltering; - int const base_freq = (int) (32768 - soundFiltering_ * 16384); - int const nyquist = stereo_buffer->sample_rate() / 2; + // Yes, I changed soundFiltering_ to soundFiltering, the reason is + // to eliminate a write-read dependency + int const base_freq = 32768 - (int) (soundFiltering * 16384.0f); + int const nyquist = stereo_buffer->sample_rate() >> 1; for ( int i = 0; i < 3; i++ ) { @@ -456,13 +454,6 @@ static void remake_stereo_buffer() pcm [0].pcm.init(); pcm [1].pcm.init(); - // APU - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; // TODO: handle out of memory - reset_apu(); - } - // Stereo_Buffer delete stereo_buffer; stereo_buffer = 0; @@ -476,7 +467,13 @@ static void remake_stereo_buffer() pcm [1].which = 1; apply_filtering(); - // Volume Level + // APU + if ( !gb_apu ) + { + gb_apu = new Gb_Apu; // TODO: handle out of memory + reset_apu(); + } + apply_muting(); apply_volume(); } @@ -595,8 +592,8 @@ static struct { gb_apu_state_t apu; // old state - u8 soundDSAValue; int soundDSBValue; + u8 soundDSAValue; } state; // Old GBA sound state format @@ -754,25 +751,16 @@ static void skip_read( gzFile in, int count ) } } -#ifdef __LIBRETRO__ -void soundSaveGame( u8 *&out ) -#else void soundSaveGame( gzFile out ) -#endif { gb_apu->save_state( &state.apu ); // Be sure areas for expansion get written as zero memset( dummy_state, 0, sizeof dummy_state ); -#ifdef __LIBRETRO__ - utilWriteDataMem( out, gba_state ); -#else utilWriteData( out, gba_state ); -#endif } -#ifndef __LIBRETRO__ static void soundReadGameOld( gzFile in, int version ) { // Read main data @@ -807,28 +795,19 @@ static void soundReadGameOld( gzFile in, int version ) (void) utilReadInt( in ); // ignore quality } -#endif #include -#ifdef __LIBRETRO__ -void soundReadGame(const u8*& in, int version ) -#else void soundReadGame( gzFile in, int version ) -#endif { // Prepare APU and default state reset_apu(); gb_apu->save_state( &state.apu ); if ( version > SAVE_GAME_VERSION_9 ) -#ifdef __LIBRETRO__ - utilReadDataMem( in, gba_state ); -#else utilReadData( in, gba_state ); else soundReadGameOld( in, version ); -#endif gb_apu->load_state( state.apu ); write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F ); diff --git a/source/vba/gba/gbafilter.cpp b/source/vba/gba/gbafilter.cpp deleted file mode 100644 index 523ec82..0000000 --- a/source/vba/gba/gbafilter.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "gbafilter.h" - -#include - -extern int systemColorDepth; -extern int systemRedShift; -extern int systemGreenShift; -extern int systemBlueShift; - -extern u16 systemColorMap16[0x10000]; -extern u32 systemColorMap32[0x10000]; - -static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12, - 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38, - 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80, - 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0}; - -// output R G B -static const unsigned char influence[3 * 3] = { 16, 4, 4, // red - 8, 16, 8, // green - 0, 8, 16};// blue - -inline void swap(short & a, short & b) -{ - short temp = a; - a = b; - b = temp; -} - -void gbafilter_pal(u16 * buf, int count) -{ - short temp[3 * 3], s; - unsigned pix; - u8 red, green, blue; - - while (count--) - { - pix = *buf; - - s = curve[(pix >> systemGreenShift) & 0x1f]; - temp[3] = s * influence[3]; - temp[4] = s * influence[4]; - temp[5] = s * influence[5]; - - s = curve[(pix >> systemRedShift) & 0x1f]; - temp[0] = s * influence[0]; - temp[1] = s * influence[1]; - temp[2] = s * influence[2]; - - s = curve[(pix >> systemBlueShift) & 0x1f]; - temp[6] = s * influence[6]; - temp[7] = s * influence[7]; - temp[8] = s * influence[8]; - - if (temp[0] < temp[3]) swap(temp[0], temp[3]); - if (temp[0] < temp[6]) swap(temp[0], temp[6]); - if (temp[3] < temp[6]) swap(temp[3], temp[6]); - temp[3] <<= 1; - temp[0] <<= 2; - temp[0] += temp[3] + temp[6]; - - red = ((int(temp[0]) * 160) >> 17) + 4; - if (red > 31) red = 31; - - if (temp[2] < temp[5]) swap(temp[2], temp[5]); - if (temp[2] < temp[8]) swap(temp[2], temp[8]); - if (temp[5] < temp[8]) swap(temp[5], temp[8]); - temp[5] <<= 1; - temp[2] <<= 2; - temp[2] += temp[5] + temp[8]; - - blue = ((int(temp[2]) * 160) >> 17) + 4; - if (blue > 31) blue = 31; - - if (temp[1] < temp[4]) swap(temp[1], temp[4]); - if (temp[1] < temp[7]) swap(temp[1], temp[7]); - if (temp[4] < temp[7]) swap(temp[4], temp[7]); - temp[4] <<= 1; - temp[1] <<= 2; - temp[1] += temp[4] + temp[7]; - - green = ((int(temp[1]) * 160) >> 17) + 4; - if (green > 31) green = 31; - - pix = red << systemRedShift; - pix += green << systemGreenShift; - pix += blue << systemBlueShift; - - *buf++ = pix; - } -} - -void gbafilter_pal32(u32 * buf, int count) -{ - short temp[3 * 3], s; - unsigned pix; - u8 red, green, blue; - - while (count--) - { - pix = *buf; - - s = curve[(pix >> systemGreenShift) & 0x1f]; - temp[3] = s * influence[3]; - temp[4] = s * influence[4]; - temp[5] = s * influence[5]; - - s = curve[(pix >> systemRedShift) & 0x1f]; - temp[0] = s * influence[0]; - temp[1] = s * influence[1]; - temp[2] = s * influence[2]; - - s = curve[(pix >> systemBlueShift) & 0x1f]; - temp[6] = s * influence[6]; - temp[7] = s * influence[7]; - temp[8] = s * influence[8]; - - if (temp[0] < temp[3]) swap(temp[0], temp[3]); - if (temp[0] < temp[6]) swap(temp[0], temp[6]); - if (temp[3] < temp[6]) swap(temp[3], temp[6]); - temp[3] <<= 1; - temp[0] <<= 2; - temp[0] += temp[3] + temp[6]; - - //red = ((int(temp[0]) * 160) >> 17) + 4; - red = ((int(temp[0]) * 160) >> 14) + 32; - - if (temp[2] < temp[5]) swap(temp[2], temp[5]); - if (temp[2] < temp[8]) swap(temp[2], temp[8]); - if (temp[5] < temp[8]) swap(temp[5], temp[8]); - temp[5] <<= 1; - temp[2] <<= 2; - temp[2] += temp[5] + temp[8]; - - //blue = ((int(temp[2]) * 160) >> 17) + 4; - blue = ((int(temp[2]) * 160) >> 14) + 32; - - if (temp[1] < temp[4]) swap(temp[1], temp[4]); - if (temp[1] < temp[7]) swap(temp[1], temp[7]); - if (temp[4] < temp[7]) swap(temp[4], temp[7]); - temp[4] <<= 1; - temp[1] <<= 2; - temp[1] += temp[4] + temp[7]; - - //green = ((int(temp[1]) * 160) >> 17) + 4; - green = ((int(temp[1]) * 160) >> 14) + 32; - - //pix = red << redshift; - //pix += green << greenshift; - //pix += blue << blueshift; - - pix = red << (systemRedShift - 3); - pix += green << (systemGreenShift - 3); - pix += blue << (systemBlueShift - 3); - - *buf++ = pix; - } -} - -// for palette mode to work with the three spoony filters in 32bpp depth - -void gbafilter_pad(u8 * buf, int count) -{ - union - { - struct - { - u8 r; - u8 g; - u8 b; - u8 a; - } part; - unsigned whole; - } - mask; - - mask.whole = 0x1f << systemRedShift; - mask.whole += 0x1f << systemGreenShift; - mask.whole += 0x1f << systemBlueShift; - - switch (systemColorDepth) - { - case 24: - while (count--) - { - *buf++ &= mask.part.r; - *buf++ &= mask.part.g; - *buf++ &= mask.part.b; - } - break; - case 32: - while (count--) - { - *((u32*)buf) &= mask.whole; - buf += 4; - } - } -} - -/* -void UpdateSystemColorMaps(int lcd) -{ - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000); - } - break; - case 24: - case 32: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000); - } - break; - } -} -*/ diff --git a/source/vba/gba/gbafilter.h b/source/vba/gba/gbafilter.h deleted file mode 100644 index 18ff53d..0000000 --- a/source/vba/gba/gbafilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "../System.h" - -void gbafilter_pal(u16 * buf, int count); -void gbafilter_pal32(u32 * buf, int count); -void gbafilter_pad(u8 * buf, int count); diff --git a/source/vbasupport.cpp b/source/vbasupport.cpp index 913861c..f46fe73 100644 --- a/source/vbasupport.cpp +++ b/source/vbasupport.cpp @@ -77,7 +77,7 @@ int systemGreenShift = 0; int systemColorDepth = 0; u16 systemGbPalette[24]; u16 systemColorMap16[0x10000]; -u32 systemColorMap32[0x10000]; +u32 *systemColorMap32 = NULL; void gbSetPalette(u32 RRGGBB[]); bool StartColorizing();