merging changes from Zopenko, libertyernie, Glitch, cebolleto, and
others
4
Makefile
@ -1,8 +1,8 @@
|
|||||||
.PHONY = all wii gc wii-clean gc-clean wii-run gc-run
|
.PHONY = all wii gc wii-clean gc-clean wii-run gc-run
|
||||||
|
|
||||||
all: wii gc
|
all: wii
|
||||||
|
|
||||||
clean: wii-clean gc-clean
|
clean: wii-clean
|
||||||
|
|
||||||
run: wii-run
|
run: wii-run
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ BUILD := build_gc
|
|||||||
SOURCES := source source/images source/sounds source/fonts source/lang \
|
SOURCES := source source/images source/sounds source/fonts source/lang \
|
||||||
source/gui source/utils source/utils/sz \
|
source/gui source/utils source/utils/sz \
|
||||||
source/vba source/vba/apu source/vba/common \
|
source/vba source/vba/apu source/vba/common \
|
||||||
source/vba/gb source/vba/gba
|
source/vba/gb source/vba/gba source/goomba source/goomba/minilzo-2.06
|
||||||
INCLUDES := source source/vba
|
INCLUDES := source source/vba
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@ -29,7 +29,8 @@ INCLUDES := source source/vba
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
|
CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
|
||||||
-DNO_SOUND -DUSE_VM -DWORDS_BIGENDIAN \
|
-DNO_SOUND -DUSE_VM -DWORDS_BIGENDIAN -DNO_LINK -DNO_FEX \
|
||||||
|
-DTILED_RENDERING \
|
||||||
-DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \
|
-DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \
|
||||||
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \
|
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \
|
||||||
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
|
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
|
||||||
|
@ -21,7 +21,7 @@ BUILD := build_wii
|
|||||||
SOURCES := source source/images source/sounds source/fonts source/lang \
|
SOURCES := source source/images source/sounds source/fonts source/lang \
|
||||||
source/gui source/utils source/utils/sz source/utils/unzip \
|
source/gui source/utils source/utils/sz source/utils/unzip \
|
||||||
source/vba source/vba/apu source/vba/common \
|
source/vba source/vba/apu source/vba/common \
|
||||||
source/vba/gb source/vba/gba
|
source/vba/gb source/vba/gba source/goomba source/goomba/minilzo-2.06
|
||||||
INCLUDES := source source/vba
|
INCLUDES := source source/vba
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@ -29,19 +29,20 @@ INCLUDES := source source/vba
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
|
CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
|
||||||
-DWORDS_BIGENDIAN \
|
-DWORDS_BIGENDIAN -DNO_LINK -DNO_FEX \
|
||||||
|
-DTILED_RENDERING \
|
||||||
-DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \
|
-DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \
|
||||||
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \
|
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \
|
||||||
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
|
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
-Wno-unused-parameter -Wno-strict-aliasing -Wno-parentheses
|
-Wno-unused-parameter -Wno-strict-aliasing -Wno-parentheses
|
||||||
CXXFLAGS = $(CFLAGS)
|
CXXFLAGS = $(CFLAGS)
|
||||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,-wrap,wiiuse_register
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# any extra libraries we wish to link with
|
# any extra libraries we wish to link with
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
LIBS := -ldi -liso9660 -lpng -lmxml -lfat -lwiiuse -lz -lbte -lasnd -logc \
|
LIBS := -ldi -liso9660 -lpng -lmxml -lfat -lwiiuse -lwupc -lz -lbte -lasnd -logc \
|
||||||
-lvorbisidec -lfreetype -ltinysmb
|
-lvorbisidec -lfreetype -ltinysmb
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
187
readme.txt
@ -1,7 +1,7 @@
|
|||||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||||
|
|
||||||
- Visual Boy Advance GX -
|
- Visual Boy Advance GX -
|
||||||
http://code.google.com/p/vba-wii
|
https://github.com/dborth/vba-wii
|
||||||
(Under GPL License)
|
(Under GPL License)
|
||||||
|
|
||||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||||
@ -18,15 +18,86 @@ With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube.
|
|||||||
* IPS/UPS patch support
|
* IPS/UPS patch support
|
||||||
* Custom controller configurations
|
* Custom controller configurations
|
||||||
* SD, USB, DVD, SMB, Zip, and 7z support
|
* SD, USB, DVD, SMB, Zip, and 7z support
|
||||||
* Compatibility based on VBA-M r927
|
* Compatibility based on VBA-M r1231
|
||||||
* MEM2 ROM Storage for fast access
|
* MEM2 ROM Storage for fast access
|
||||||
* Auto frame skip for those core heavy games
|
* Auto frame skip (optional) for those core heavy games
|
||||||
* Turbo speed, video zooming, widescreen, and unfiltered video options
|
* 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|
|
|0O×øo· UPDATE HISTORY ·oø×O0|
|
||||||
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
|
||||||
|
|
||||||
|
[2.3.3] - Zopenko
|
||||||
|
|
||||||
|
* fixes the gc pad down on file browser
|
||||||
|
* added koston default green gb color screen
|
||||||
|
* added the screenshot/preview button
|
||||||
|
* added the wiiupro icon on the controller settings
|
||||||
|
* increased and centered the screenshot image
|
||||||
|
* added the screenshot white image background
|
||||||
|
|
||||||
|
[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]
|
[2.2.8 - July 29, 2012]
|
||||||
|
|
||||||
* Fixed lag with GameCube controllers
|
* Fixed lag with GameCube controllers
|
||||||
@ -508,9 +579,8 @@ Z = Gameboy A Button
|
|||||||
C = Gameboy B Button
|
C = Gameboy B Button
|
||||||
|
|
||||||
Classic Controller:
|
Classic Controller:
|
||||||
Use the buttons as labelled.
|
B = Gameboy A Button
|
||||||
A = Gameboy A Button
|
Y = Gameboy B Button
|
||||||
B = Gameboy B Button
|
|
||||||
R = Gameboy R Button
|
R = Gameboy R Button
|
||||||
L = Gameboy L Button
|
L = Gameboy L Button
|
||||||
|
|
||||||
@ -535,6 +605,43 @@ to the main menu and B again to return to the game.
|
|||||||
A+B, Spacebar, or right analog stick: fast forward
|
A+B, Spacebar, or right analog stick: fast forward
|
||||||
Right analog stick: zoom (if enabled)
|
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 ]=-
|
-=[ Match Wii Controls ]=-
|
||||||
|
|
||||||
Special Wii controls exist for the following games:
|
Special Wii controls exist for the following games:
|
||||||
@ -577,8 +684,8 @@ Medal Of Honour Underground, Medal Of Honour Infiltrator
|
|||||||
|
|
||||||
One Piece can be played with One Piece Unlimited Adventure controls.
|
One Piece can be played with One Piece Unlimited Adventure controls.
|
||||||
|
|
||||||
Boktai 1, Boktai 2, Boktai 3, Kirby's Tilt n Tumble, and WarioWare Twisted
|
Boktai 1, Boktai 2, Boktai 3, and Kirby's Tilt n Tumble can be played with
|
||||||
can be played with controls I designed for them.
|
controls designed for them.
|
||||||
|
|
||||||
-=[ Zelda, Match Wii Controls ]=-
|
-=[ Zelda, Match Wii Controls ]=-
|
||||||
|
|
||||||
@ -740,8 +847,11 @@ A = spin attack
|
|||||||
X/Y = shoot, run, hold on to things, yoshi's tongue, etc.
|
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.
|
ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp.
|
||||||
+ = pause
|
+ = pause
|
||||||
L/R sometimes look around
|
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 ]=-
|
-=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=-
|
||||||
|
|
||||||
@ -834,20 +944,9 @@ Z or 1 = change element, or change subscreen (L)
|
|||||||
|
|
||||||
-=[ WarioWare Twisted, Match Wii Controls ]=-
|
-=[ WarioWare Twisted, Match Wii Controls ]=-
|
||||||
|
|
||||||
Turn "Match Wii Controls" ON to use these 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
|
||||||
WarioWare Twisted uses similar controls to the Gameboy game.
|
will need to go back to VBA-GX 2.2.8 to play it.
|
||||||
|
|
||||||
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 ]=-
|
-=[ Kirby's Tilt n Tumble, Match Wii Controls ]=-
|
||||||
|
|
||||||
@ -987,11 +1086,51 @@ Z = grab
|
|||||||
right analog stick = fast forward
|
right analog stick = fast forward
|
||||||
1 = select (maybe does nothing)
|
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 ]=-
|
-=[ Credits ]=-
|
||||||
|
|
||||||
Coding & menu design Tantric
|
Coding & menu design Tantric
|
||||||
|
Codebase update & Goomba libertyernie
|
||||||
|
Menu screenshots cebolleto
|
||||||
|
GBA tiled rendering bgK (for RetroArch)
|
||||||
Additional coding Carl Kenner, dancinninjac
|
Additional coding Carl Kenner, dancinninjac
|
||||||
Menu artwork the3seashells
|
Menu artwork the3seashells
|
||||||
Menu sound Peter de Man
|
Menu sound Peter de Man
|
||||||
@ -1009,6 +1148,6 @@ right analog stick = fast forward
|
|||||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||||
|
|
||||||
VBAGX Web Site
|
VBAGX Web Site
|
||||||
http://code.google.com/p/vba-wii
|
https://github.com/dborth/vba-wii
|
||||||
|
|
||||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||||
|
@ -35,6 +35,7 @@ BROWSERINFO browser;
|
|||||||
BROWSERENTRY * browserList = NULL; // list of files/folders in browser
|
BROWSERENTRY * browserList = NULL; // list of files/folders in browser
|
||||||
|
|
||||||
char szpath[MAXPATHLEN];
|
char szpath[MAXPATHLEN];
|
||||||
|
char szname[MAXPATHLEN];
|
||||||
bool inSz = false;
|
bool inSz = false;
|
||||||
|
|
||||||
char ROMFilename[512];
|
char ROMFilename[512];
|
||||||
@ -211,6 +212,8 @@ int UpdateDirName()
|
|||||||
|
|
||||||
/* remove last subdirectory name */
|
/* remove last subdirectory name */
|
||||||
size = strlen(browser.dir) - size - 1;
|
size = strlen(browser.dir) - size - 1;
|
||||||
|
strncpy(GCSettings.LastFileLoaded, &browser.dir[size], strlen(browser.dir) - size - 1); //set as loaded file the previous dir
|
||||||
|
GCSettings.LastFileLoaded[strlen(browser.dir) - size - 1] = 0;
|
||||||
browser.dir[size] = 0;
|
browser.dir[size] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +258,24 @@ bool MakeFilePath(char filepath[], int type, char * filename, int filenum)
|
|||||||
sprintf(temppath, "%s%s",browser.dir,browserList[browser.selIndex].filename);
|
sprintf(temppath, "%s%s",browser.dir,browserList[browser.selIndex].filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type == FILE_BORDER_PNG)
|
||||||
|
{
|
||||||
|
const char* loadedpath = filename;
|
||||||
|
if (loadedpath == NULL) loadedpath = "default";
|
||||||
|
// Ensure that loadedname contains only the filename, not the path
|
||||||
|
const char* loadedname = strrchr(loadedpath, '/');
|
||||||
|
if (loadedname == NULL) loadedname = loadedpath;
|
||||||
|
|
||||||
|
// Check path length
|
||||||
|
if ((strlen(pathPrefix[GCSettings.LoadMethod]) + strlen(GCSettings.BorderFolder) + strlen(loadedname)) >= MAXPATHLEN) {
|
||||||
|
ErrorPrompt("Maximum filepath length reached!");
|
||||||
|
filepath[0] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StripExt(file, loadedname);
|
||||||
|
sprintf(temppath, "%s%s/%s.png", pathPrefix[GCSettings.LoadMethod], GCSettings.BorderFolder, file);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(GCSettings.SaveMethod == DEVICE_AUTO)
|
if(GCSettings.SaveMethod == DEVICE_AUTO)
|
||||||
@ -277,7 +298,14 @@ bool MakeFilePath(char filepath[], int type, char * filename, int filenum)
|
|||||||
if(filenum == -1)
|
if(filenum == -1)
|
||||||
sprintf(file, "%s.%s", filename, ext);
|
sprintf(file, "%s.%s", filename, ext);
|
||||||
else if(filenum == 0)
|
else if(filenum == 0)
|
||||||
|
if (GCSettings.AppendAuto <= 0)
|
||||||
|
{
|
||||||
|
sprintf(file, "%s.%s", filename, ext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
sprintf(file, "%s Auto.%s", filename, ext);
|
sprintf(file, "%s Auto.%s", filename, ext);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sprintf(file, "%s %i.%s", filename, filenum, ext);
|
sprintf(file, "%s %i.%s", filename, filenum, ext);
|
||||||
}
|
}
|
||||||
@ -344,7 +372,7 @@ bool IsSz()
|
|||||||
*
|
*
|
||||||
* Strips an extension from a filename
|
* Strips an extension from a filename
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void StripExt(char* returnstring, char * inputstring)
|
void StripExt(char* returnstring, const char * inputstring)
|
||||||
{
|
{
|
||||||
char* loc_dot;
|
char* loc_dot;
|
||||||
|
|
||||||
@ -436,12 +464,11 @@ void ShortenFilename(char * returnstring, char * inputstring)
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
int BrowserLoadSz()
|
int BrowserLoadSz()
|
||||||
{
|
{
|
||||||
char filepath[MAXPATHLEN];
|
memset(szpath, 0, MAXPATHLEN);
|
||||||
memset(filepath, 0, MAXPATHLEN);
|
strncpy(szpath, browser.dir, strlen(browser.dir) - 1);
|
||||||
|
|
||||||
// we'll store the 7z filepath for extraction later
|
strncpy(szname, strrchr(szpath, '/') + 1, strrchr(szpath, '.') - strrchr(szpath, '/'));
|
||||||
if(!MakeFilePath(szpath, FILE_ROM))
|
*strrchr(szname, '.') = '\0';
|
||||||
return 0;
|
|
||||||
|
|
||||||
int szfiles = SzParse(szpath);
|
int szfiles = SzParse(szpath);
|
||||||
if(szfiles)
|
if(szfiles)
|
||||||
@ -469,7 +496,7 @@ int BrowserLoadFile()
|
|||||||
|
|
||||||
// store the filename (w/o ext) - used for sram/freeze naming
|
// store the filename (w/o ext) - used for sram/freeze naming
|
||||||
StripExt(ROMFilename, browserList[browser.selIndex].filename);
|
StripExt(ROMFilename, browserList[browser.selIndex].filename);
|
||||||
strcpy(loadedFile, browserList[browser.selIndex].filename);
|
snprintf(GCSettings.LastFileLoaded, MAXPATHLEN, "%s", browserList[browser.selIndex].filename);
|
||||||
|
|
||||||
loadingFile = true;
|
loadingFile = true;
|
||||||
ROMLoaded = LoadVBAROM();
|
ROMLoaded = LoadVBAROM();
|
||||||
@ -516,12 +543,22 @@ int BrowserChangeFolder()
|
|||||||
if(!UpdateDirName())
|
if(!UpdateDirName())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
HaltParseThread(); // halt parsing
|
HaltParseThread();
|
||||||
CleanupPath(browser.dir);
|
CleanupPath(browser.dir);
|
||||||
ResetBrowser(); // reset browser
|
ResetBrowser();
|
||||||
|
|
||||||
if(browser.dir[0] != 0)
|
if(browser.dir[0] != 0)
|
||||||
ParseDirectory();
|
{
|
||||||
|
if(strstr(browser.dir, ".7z"))
|
||||||
|
{
|
||||||
|
BrowserLoadSz();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ParseDirectory(true, true);
|
||||||
|
}
|
||||||
|
FindAndSelectLastLoadedFile();
|
||||||
|
}
|
||||||
|
|
||||||
if(browser.numEntries == 0)
|
if(browser.numEntries == 0)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,7 @@ extern bool ROMLoaded;
|
|||||||
extern bool loadingFile;
|
extern bool loadingFile;
|
||||||
extern char szpath[MAXPATHLEN];
|
extern char szpath[MAXPATHLEN];
|
||||||
extern bool inSz;
|
extern bool inSz;
|
||||||
|
extern char szname[MAXPATHLEN];
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -64,7 +65,7 @@ int OpenGameList();
|
|||||||
int autoLoadMethod();
|
int autoLoadMethod();
|
||||||
int autoSaveMethod(bool silent);
|
int autoSaveMethod(bool silent);
|
||||||
int FileSortCallback(const void *f1, const void *f2);
|
int FileSortCallback(const void *f1, const void *f2);
|
||||||
void StripExt(char* returnstring, char * inputstring);
|
void StripExt(char* returnstring, const char* inputstring);
|
||||||
bool IsSz();
|
bool IsSz();
|
||||||
void ResetBrowser();
|
void ResetBrowser();
|
||||||
bool AddBrowserEntry();
|
bool AddBrowserEntry();
|
||||||
|
@ -104,6 +104,8 @@ extern const u8 icon_settings_gamecube_png[];
|
|||||||
extern const u32 icon_settings_gamecube_png_size;
|
extern const u32 icon_settings_gamecube_png_size;
|
||||||
extern const u8 icon_settings_nunchuk_png[];
|
extern const u8 icon_settings_nunchuk_png[];
|
||||||
extern const u32 icon_settings_nunchuk_png_size;
|
extern const u32 icon_settings_nunchuk_png_size;
|
||||||
|
extern const u8 icon_settings_wiiupro_png[];
|
||||||
|
extern const u32 icon_settings_wiiupro_png_size;
|
||||||
|
|
||||||
extern const u8 icon_settings_file_png[];
|
extern const u8 icon_settings_file_png[];
|
||||||
extern const u32 icon_settings_file_png_size;
|
extern const u32 icon_settings_file_png_size;
|
||||||
@ -115,6 +117,8 @@ extern const u8 icon_settings_network_png[];
|
|||||||
extern const u32 icon_settings_network_png_size;
|
extern const u32 icon_settings_network_png_size;
|
||||||
extern const u8 icon_settings_video_png[];
|
extern const u8 icon_settings_video_png[];
|
||||||
extern const u32 icon_settings_video_png_size;
|
extern const u32 icon_settings_video_png_size;
|
||||||
|
extern const u8 icon_settings_screenshot_png[];
|
||||||
|
extern const u32 icon_settings_screenshot_png_size;
|
||||||
|
|
||||||
extern const u8 button_png[];
|
extern const u8 button_png[];
|
||||||
extern const u32 button_png_size;
|
extern const u32 button_png_size;
|
||||||
@ -242,6 +246,9 @@ extern const u32 bg_game_selection_png_size;
|
|||||||
extern const u8 bg_game_selection_entry_png[];
|
extern const u8 bg_game_selection_entry_png[];
|
||||||
extern const u32 bg_game_selection_entry_png_size;
|
extern const u32 bg_game_selection_entry_png_size;
|
||||||
|
|
||||||
|
extern const u8 bg_preview_png[];
|
||||||
|
extern const u32 bg_preview_png_size;
|
||||||
|
|
||||||
extern const u8 scrollbar_png[];
|
extern const u8 scrollbar_png[];
|
||||||
extern const u32 scrollbar_png_size;
|
extern const u32 scrollbar_png_size;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ bool isMounted[7] = { false, false, false, false, false, false, false };
|
|||||||
|
|
||||||
// folder parsing thread
|
// folder parsing thread
|
||||||
static lwp_t parsethread = LWP_THREAD_NULL;
|
static lwp_t parsethread = LWP_THREAD_NULL;
|
||||||
static DIR * dir = NULL;
|
static DIR *dir = NULL;
|
||||||
static bool parseHalt = true;
|
static bool parseHalt = true;
|
||||||
static bool parseFilter = true;
|
static bool parseFilter = true;
|
||||||
static bool ParseDirEntries();
|
static bool ParseDirEntries();
|
||||||
@ -490,6 +490,40 @@ bool GetFileSize(int i)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FindAndSelectLastLoadedFile ()
|
||||||
|
{
|
||||||
|
int indexFound = -1;
|
||||||
|
|
||||||
|
for(int j=1; j < browser.numEntries; j++)
|
||||||
|
{
|
||||||
|
if(strcmp(browserList[j].filename, GCSettings.LastFileLoaded) == 0)
|
||||||
|
{
|
||||||
|
indexFound = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move to this file
|
||||||
|
if(indexFound > 0)
|
||||||
|
{
|
||||||
|
if(indexFound >= FILE_PAGESIZE)
|
||||||
|
{
|
||||||
|
int newIndex = (floor(indexFound/(float)FILE_PAGESIZE)) * FILE_PAGESIZE;
|
||||||
|
|
||||||
|
if(newIndex + FILE_PAGESIZE > browser.numEntries)
|
||||||
|
newIndex = browser.numEntries - FILE_PAGESIZE;
|
||||||
|
|
||||||
|
if(newIndex < 0)
|
||||||
|
newIndex = 0;
|
||||||
|
|
||||||
|
browser.pageIndex = newIndex;
|
||||||
|
}
|
||||||
|
browser.selIndex = indexFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectLoadedFile = 2; // selecting done
|
||||||
|
}
|
||||||
|
|
||||||
static bool ParseDirEntries()
|
static bool ParseDirEntries()
|
||||||
{
|
{
|
||||||
if(!dir)
|
if(!dir)
|
||||||
@ -578,39 +612,6 @@ static bool ParseDirEntries()
|
|||||||
closedir(dir); // close directory
|
closedir(dir); // close directory
|
||||||
dir = NULL;
|
dir = NULL;
|
||||||
|
|
||||||
// try to find and select the last loaded file
|
|
||||||
if(selectLoadedFile == 1 && !parseHalt && loadedFile[0] != 0 && browser.dir[0] != 0)
|
|
||||||
{
|
|
||||||
int indexFound = -1;
|
|
||||||
|
|
||||||
for(int j=1; j < browser.numEntries; j++)
|
|
||||||
{
|
|
||||||
if(strcmp(browserList[j].filename, loadedFile) == 0)
|
|
||||||
{
|
|
||||||
indexFound = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// move to this file
|
|
||||||
if(indexFound > 0)
|
|
||||||
{
|
|
||||||
if(indexFound >= FILE_PAGESIZE)
|
|
||||||
{
|
|
||||||
int newIndex = (floor(indexFound/(float)FILE_PAGESIZE)) * FILE_PAGESIZE;
|
|
||||||
|
|
||||||
if(newIndex + FILE_PAGESIZE > browser.numEntries)
|
|
||||||
newIndex = browser.numEntries - FILE_PAGESIZE;
|
|
||||||
|
|
||||||
if(newIndex < 0)
|
|
||||||
newIndex = 0;
|
|
||||||
|
|
||||||
browser.pageIndex = newIndex;
|
|
||||||
}
|
|
||||||
browser.selIndex = indexFound;
|
|
||||||
}
|
|
||||||
selectLoadedFile = 2; // selecting done
|
|
||||||
}
|
|
||||||
return false; // no more entries
|
return false; // no more entries
|
||||||
}
|
}
|
||||||
return true; // more entries
|
return true; // more entries
|
||||||
@ -824,6 +825,12 @@ LoadFile (char * rbuffer, char *filepath, size_t length, bool silent)
|
|||||||
|
|
||||||
while(!feof(file))
|
while(!feof(file))
|
||||||
{
|
{
|
||||||
|
// If the size requested is *less* than the filesize, only read that much - we don't want to overrun the buffer
|
||||||
|
int toread = 4096;
|
||||||
|
if (length > 0 && offset+toread > length) {
|
||||||
|
toread = length - offset;
|
||||||
|
}
|
||||||
|
|
||||||
ShowProgress ("Loading...", offset, size);
|
ShowProgress ("Loading...", offset, size);
|
||||||
readsize = fread (rbuffer + offset, 1, 4096, file); // read in next chunk
|
readsize = fread (rbuffer + offset, 1, 4096, file); // read in next chunk
|
||||||
|
|
||||||
@ -831,6 +838,9 @@ LoadFile (char * rbuffer, char *filepath, size_t length, bool silent)
|
|||||||
break; // reading finished (or failed)
|
break; // reading finished (or failed)
|
||||||
|
|
||||||
offset += readsize;
|
offset += readsize;
|
||||||
|
if (length > 0 && offset >= length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
size = offset;
|
size = offset;
|
||||||
CancelAction();
|
CancelAction();
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <fat.h>
|
#include <fat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define SAVEBUFFERSIZE (1024 * 1024 * 2)
|
#define SAVEBUFFERSIZE (1024 * 512)
|
||||||
|
|
||||||
void InitDeviceThread();
|
void InitDeviceThread();
|
||||||
void ResumeDeviceThread();
|
void ResumeDeviceThread();
|
||||||
@ -32,6 +32,7 @@ bool ChangeInterface(int device, bool silent);
|
|||||||
bool ChangeInterface(char * filepath, bool silent);
|
bool ChangeInterface(char * filepath, bool silent);
|
||||||
void CreateAppPath(char * origpath);
|
void CreateAppPath(char * origpath);
|
||||||
bool GetFileSize(int i);
|
bool GetFileSize(int i);
|
||||||
|
void FindAndSelectLastLoadedFile();
|
||||||
int ParseDirectory(bool waitParse = false, bool filter = true);
|
int ParseDirectory(bool waitParse = false, bool filter = true);
|
||||||
void AllocSaveBuffer();
|
void AllocSaveBuffer();
|
||||||
void FreeSaveBuffer();
|
void FreeSaveBuffer();
|
||||||
|
@ -1540,3 +1540,119 @@ u32 CastlevaniaCircleMoonInput(unsigned short pad) {
|
|||||||
return J;
|
return J;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 KD_NOR[64] = {
|
||||||
|
0x7f, 0x00, 0x98, 0x67, 0x00, 0x99, 0x00, 0x89, 0x00, 0xa1, 0x00, 0xb1, 0x10, 0xa9, 0x18, 0x67,
|
||||||
|
0xff, 0x00, 0x81, 0x7e, 0x00, 0x81, 0x00, 0xb9, 0x10, 0xa9, 0x00, 0xb9, 0x00, 0x81, 0x81, 0x7e,
|
||||||
|
0xfe, 0x00, 0x03, 0xfc, 0x01, 0x82, 0x00, 0xb9, 0x00, 0xb9, 0x01, 0x82, 0x00, 0xb9, 0x10, 0xef,
|
||||||
|
0x00, 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
u8 KD_BAT[64] = {
|
||||||
|
0x7f, 0x00, 0x83, 0x7c, 0x01, 0x82, 0x00, 0xb9, 0x01, 0x82, 0x00, 0xb9, 0x00, 0x81, 0x01, 0x7e,
|
||||||
|
0xff, 0x00, 0x81, 0x7e, 0x00, 0x81, 0x00, 0xb9, 0x00, 0xb9, 0x00, 0x81, 0x00, 0xb9, 0x10, 0xef,
|
||||||
|
0xfe, 0x00, 0x00, 0xff, 0x00, 0x81, 0x00, 0xe7, 0xc3, 0x24, 0xc3, 0x24, 0xc3, 0x24, 0xc2, 0x3c,
|
||||||
|
0x00, 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
u8 KD_ACTUAL[64];
|
||||||
|
|
||||||
|
u8 KD_NOR_GRAPHICS[128] = {
|
||||||
|
0x00, 0x00, 0x00, 0x0f, 0x04, 0x07, 0x18, 0x1f, 0x0d, 0x0e, 0x40, 0x7f, 0x18, 0x1f, 0x70, 0x7f,
|
||||||
|
0xc0, 0xff, 0x70, 0x7f, 0x01, 0x3e, 0x0c, 0x0f, 0x3e, 0x3f, 0x10, 0x1f, 0x06, 0x07, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0xe0, 0xe4, 0x18, 0x3a, 0xc4, 0xfc, 0x02, 0x3d, 0xc2, 0xfe, 0x01, 0x3e, 0xc1,
|
||||||
|
0x7e, 0x81, 0x3e, 0xc1, 0xfd, 0x02, 0x7c, 0x82, 0x1a, 0xe4, 0xe4, 0x18, 0x10, 0xe0, 0x00, 0x00,
|
||||||
|
0x04, 0x03, 0x13, 0x0c, 0x2f, 0x10, 0x5f, 0x20, 0x5f, 0x20, 0x3f, 0x40, 0x2a, 0x55, 0x2a, 0x55,
|
||||||
|
0x08, 0x77, 0x00, 0x7f, 0x28, 0x7f, 0x1a, 0x5f, 0x13, 0x17, 0x01, 0x05, 0x05, 0x05, 0x00, 0x00,
|
||||||
|
0x20, 0xc0, 0xc8, 0x30, 0xf4, 0x08, 0xf8, 0x04, 0xfa, 0x04, 0xf4, 0x0a, 0xb4, 0x4a, 0x24, 0xda,
|
||||||
|
0x20, 0xde, 0x0a, 0xfe, 0x1a, 0xfe, 0x18, 0xfc, 0x4c, 0xec, 0x48, 0xe8, 0xc0, 0xc0, 0x80, 0x80};
|
||||||
|
u8 KD_ACTUAL_GRAPHICS[128];
|
||||||
|
|
||||||
|
bool KD_WeaponPressed = false;
|
||||||
|
s8 KD_LastWeapon; // -1 for selected weapon, 0 for NOR, 4 for BAT
|
||||||
|
u8 KD_ActualItem; // Item selected by the player (byte in memory)
|
||||||
|
|
||||||
|
void KD_WeaponToMemory() {
|
||||||
|
// If the fourth 8x8 tile of the weapon indicator doesn't contain the "+" icon I made, the weapon has been changed in the game and has to be updated in memory.
|
||||||
|
bool hasPlusIcon = true;
|
||||||
|
for (int i=48; i<64; i++) {
|
||||||
|
if (gbReadMemory(0x9110+i) != KD_BAT[i]) {
|
||||||
|
hasPlusIcon = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasPlusIcon) return;
|
||||||
|
|
||||||
|
KD_ActualItem = gbReadMemory(0xC8CB);
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
KD_ACTUAL[i] = gbReadMemory(0x9110+i);
|
||||||
|
}
|
||||||
|
for (int i=0; i<128; i++) {
|
||||||
|
KD_ACTUAL_GRAPHICS[i] = gbReadMemory(0x8f40+i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 KidDraculaInput(unsigned short pad) {
|
||||||
|
// Only Nunchuk and Classic controls available
|
||||||
|
// Wiimote and Gamecube controls depend on user configuration
|
||||||
|
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeWiimote(pad) | DecodeClassic(pad);
|
||||||
|
bool JumpButton=0, ShootButton=0, PauseButton=0, SelectButton=0, SpeedButton=0, NorButton=0, BatButton=0;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
WPADData * wp = WPAD_Data(pad);
|
||||||
|
if (wp->exp.type == WPAD_EXP_NUNCHUK) {
|
||||||
|
JumpButton = wp->btns_h & WPAD_BUTTON_A;
|
||||||
|
ShootButton = wp->btns_h & WPAD_BUTTON_B;
|
||||||
|
PauseButton = wp->btns_h & WPAD_BUTTON_PLUS;
|
||||||
|
SelectButton = wp->btns_h & WPAD_BUTTON_MINUS;
|
||||||
|
SpeedButton = wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2;
|
||||||
|
NorButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_Z;
|
||||||
|
BatButton = wp->btns_h & WPAD_NUNCHUK_BUTTON_C;
|
||||||
|
} else if (wp->exp.type == WPAD_EXP_CLASSIC) {
|
||||||
|
JumpButton = wp->btns_h & (WPAD_CLASSIC_BUTTON_B | WPAD_CLASSIC_BUTTON_A);
|
||||||
|
ShootButton = wp->btns_h & WPAD_CLASSIC_BUTTON_Y;
|
||||||
|
PauseButton = wp->btns_h & WPAD_CLASSIC_BUTTON_PLUS;
|
||||||
|
SelectButton = wp->btns_h & WPAD_CLASSIC_BUTTON_MINUS;
|
||||||
|
SpeedButton = wp->btns_h & (WPAD_CLASSIC_BUTTON_ZL | WPAD_CLASSIC_BUTTON_FULL_L);
|
||||||
|
NorButton = wp->btns_h & WPAD_CLASSIC_BUTTON_X;
|
||||||
|
BatButton = wp->btns_h & (WPAD_CLASSIC_BUTTON_ZR | WPAD_CLASSIC_BUTTON_FULL_R);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (JumpButton) J |= VBA_BUTTON_A;
|
||||||
|
if (ShootButton && !(KD_WeaponPressed && KD_LastWeapon != -1)) {
|
||||||
|
J |= VBA_BUTTON_B;
|
||||||
|
KD_LastWeapon = -1;
|
||||||
|
// Insert original weapon and graphics
|
||||||
|
KD_WeaponToMemory();
|
||||||
|
gbWriteMemory(0xC8CB, KD_ActualItem);
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
gbWriteMemory(0x9110+i, KD_ACTUAL[i]);
|
||||||
|
}
|
||||||
|
for (int i=0; i<128; i++) {
|
||||||
|
gbWriteMemory(0x8f40+i, KD_ACTUAL_GRAPHICS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NorButton && !(KD_WeaponPressed && KD_LastWeapon != 0)) {
|
||||||
|
J |= VBA_BUTTON_B;
|
||||||
|
KD_LastWeapon = 0;
|
||||||
|
// Insert NOR weapon and graphics
|
||||||
|
KD_WeaponToMemory();
|
||||||
|
gbWriteMemory(0xC8CB, 0);
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
gbWriteMemory(0x9110+i, KD_NOR[i]);
|
||||||
|
}
|
||||||
|
for (int i=0; i<128; i++) {
|
||||||
|
gbWriteMemory(0x8f40+i, KD_NOR_GRAPHICS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (BatButton && !(KD_WeaponPressed && KD_LastWeapon != 4)) {
|
||||||
|
J |= VBA_BUTTON_B;
|
||||||
|
KD_LastWeapon = 4;
|
||||||
|
// Insert BAT weapon and graphics
|
||||||
|
KD_WeaponToMemory();
|
||||||
|
gbWriteMemory(0xC8CB, 4);
|
||||||
|
for (int i=0; i<64; i++) {
|
||||||
|
gbWriteMemory(0x9110+i, KD_BAT[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PauseButton) J |= VBA_BUTTON_START;
|
||||||
|
if (SelectButton) J |= VBA_BUTTON_SELECT;
|
||||||
|
if (SpeedButton) J |= VBA_SPEED;
|
||||||
|
KD_WeaponPressed = (ShootButton || NorButton || BatButton);
|
||||||
|
return J;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
#define CVCLASSIC gid('F','A','D')
|
#define CVCLASSIC gid('F','A','D')
|
||||||
#define CVDOUBLE gid('B','X','K')
|
#define CVDOUBLE gid('B','X','K')
|
||||||
|
|
||||||
|
#define KIDDRACULA 0xFF0014
|
||||||
|
|
||||||
#define MARBLEMADNESS 0xFF000A
|
#define MARBLEMADNESS 0xFF000A
|
||||||
|
|
||||||
@ -205,6 +205,7 @@ u32 CastlevaniaAdventureInput(unsigned short pad);
|
|||||||
u32 CastlevaniaBelmontInput(unsigned short pad);
|
u32 CastlevaniaBelmontInput(unsigned short pad);
|
||||||
u32 CastlevaniaLegendsInput(unsigned short pad);
|
u32 CastlevaniaLegendsInput(unsigned short pad);
|
||||||
u32 CastlevaniaCircleMoonInput(unsigned short pad);
|
u32 CastlevaniaCircleMoonInput(unsigned short pad);
|
||||||
|
u32 KidDraculaInput(unsigned short pad);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "vbagx.h"
|
#include "vbagx.h"
|
||||||
#include "fileop.h"
|
#include "fileop.h"
|
||||||
@ -367,14 +368,15 @@ int SzParse(char * filepath)
|
|||||||
|
|
||||||
int device;
|
int device;
|
||||||
|
|
||||||
if(!FindDevice(browser.dir, &device) || !GetFileSize(browser.selIndex))
|
struct stat filestat;
|
||||||
|
if(stat(filepath, &filestat) < 0)
|
||||||
|
return 0;
|
||||||
|
unsigned int filelen = filestat.st_size;
|
||||||
|
|
||||||
|
if(!FindDevice(filepath, &device) || !filelen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int nbfiles = 0;
|
int nbfiles = 0;
|
||||||
|
|
||||||
// save the length/offset of this file
|
|
||||||
unsigned int filelen = browserList[browser.selIndex].length;
|
|
||||||
|
|
||||||
// setup archive stream
|
// setup archive stream
|
||||||
SzArchiveStream.offset = 0;
|
SzArchiveStream.offset = 0;
|
||||||
SzArchiveStream.len = filelen;
|
SzArchiveStream.len = filelen;
|
||||||
@ -423,7 +425,7 @@ int SzParse(char * filepath)
|
|||||||
|
|
||||||
// add '..' folder in case the user wants exit the 7z
|
// add '..' folder in case the user wants exit the 7z
|
||||||
AddBrowserEntry();
|
AddBrowserEntry();
|
||||||
|
sprintf(browserList[0].filename, "..");
|
||||||
sprintf(browserList[0].displayname, "Up One Level");
|
sprintf(browserList[0].displayname, "Up One Level");
|
||||||
browserList[0].isdir = 1;
|
browserList[0].isdir = 1;
|
||||||
browserList[0].length = filelen;
|
browserList[0].length = filelen;
|
||||||
@ -452,6 +454,12 @@ int SzParse(char * filepath)
|
|||||||
// parse information about this file to the file list structure
|
// parse information about this file to the file list structure
|
||||||
snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name);
|
snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name);
|
||||||
StripExt(browserList[SzJ].displayname, browserList[SzJ].filename);
|
StripExt(browserList[SzJ].displayname, browserList[SzJ].filename);
|
||||||
|
char* strPos = strstr(browserList[SzJ].displayname, szname);
|
||||||
|
if(strPos)
|
||||||
|
{
|
||||||
|
snprintf(browserList[SzJ].displayname, MAXJOLIET, "%s", strPos + strlen(szname));
|
||||||
|
}
|
||||||
|
|
||||||
browserList[SzJ].length = SzF->Size; // filesize
|
browserList[SzJ].length = SzF->Size; // filesize
|
||||||
browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags)
|
browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags)
|
||||||
browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number
|
browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number
|
||||||
|
6
source/goomba/README.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
goombasav.c is designed to edit the compressed SRAM data of the Goomba and Goomba Color emulators. It can extract and replace the compressed Game Boy / Game Boy Color SRAM data. It can't edit savestate data or add new SRAM (yet).
|
||||||
|
|
||||||
|
goombarom.c can find uncompressed Game Boy ROMs within larger files (e.g. a Goomba Color .gba ROM, or a .tar archive.) It was written for my fork of TGB Dual.
|
||||||
|
|
||||||
|
https://github.com/libertyernie/goombasav
|
||||||
|
https://github.com/libertyernie/tgbdual
|
84
source/goomba/goombarom.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* goombarom.c - functions to find uncompressed Game Boy ROM images
|
||||||
|
stored within a larger file (e.g. Goomba Color ROMs, TAR archives)
|
||||||
|
|
||||||
|
Copyright (C) 2014 libertyernie
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
When compiling in Visual Studio, set all goombarom files to compile
|
||||||
|
as C++ code (Properties -> C/C++ -> Advanced -> Compile As.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "goombarom.h"
|
||||||
|
|
||||||
|
const char NINTENDO_LOGO_GB[48] = { 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E };
|
||||||
|
char gb_title_buffer[16];
|
||||||
|
|
||||||
|
/* Finds the (expected) size of a Game Boy ROM, given a pointer to the start
|
||||||
|
of the ROM image. */
|
||||||
|
unsigned int gb_rom_size(const void* rom_start) {
|
||||||
|
const char* ptr = (const char*)rom_start;
|
||||||
|
return 0x8000 << ptr[0x148];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finds the first Game Boy ROM in the given data block by looking for the
|
||||||
|
Nintendo logo that shows when you turn the Game Boy on. If no valid data is
|
||||||
|
found, this method will return NULL. */
|
||||||
|
const void* gb_first_rom(const void* data, size_t length) {
|
||||||
|
const char* ptr = (const char*)data;
|
||||||
|
const char* end = ptr + length;
|
||||||
|
int logo_pos = 0;
|
||||||
|
while (ptr < end) {
|
||||||
|
if (*ptr == NINTENDO_LOGO_GB[logo_pos]) {
|
||||||
|
// match
|
||||||
|
logo_pos++;
|
||||||
|
if (logo_pos == 48) { // matched all of GB logo - on last byte (0x133)
|
||||||
|
return ptr - 0x133;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no match, try again
|
||||||
|
if (logo_pos > 0) {
|
||||||
|
ptr -= logo_pos;
|
||||||
|
logo_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a pointer to the next Game Boy ROM in the data. If no valid Game
|
||||||
|
Boy ROM is found between *data and *data+length, starting at *rom, this method
|
||||||
|
will return NULL.*/
|
||||||
|
const void* gb_next_rom(const void* data, size_t length, const void* rom) {
|
||||||
|
size_t diff = (const char*)rom - (const char*)data;
|
||||||
|
if (diff > length) {
|
||||||
|
//fprintf(stderr, "*data and *rom are farther apart than length param\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t effective_length = length - diff;
|
||||||
|
if (effective_length <= 0x200) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return gb_first_rom((const char*)rom + 0x134, effective_length - 0x134);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* gb_get_title(const void* rom, char* buffer) {
|
||||||
|
char* title = buffer != NULL ? buffer : gb_title_buffer;
|
||||||
|
title[15] = '\0';
|
||||||
|
memcpy(title, (char*)rom + 0x134, 15);
|
||||||
|
return title;
|
||||||
|
}
|
43
source/goomba/goombarom.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* goombarom.h - functions to find uncompressed Game Boy ROM images
|
||||||
|
stored within a larger file (e.g. Goomba Color ROMs, TAR archives)
|
||||||
|
|
||||||
|
Copyright (C) 2014 libertyernie
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
When compiling in Visual Studio, set all goombarom files to compile
|
||||||
|
as C++ code (Properties -> C/C++ -> Advanced -> Compile As.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* Finds the (expected) size of a Game Boy ROM, given a pointer to the start
|
||||||
|
of the ROM image. */
|
||||||
|
unsigned int gb_rom_size(const void* rom_start);
|
||||||
|
|
||||||
|
/* Finds the first Game Boy ROM in the given data block by looking for the
|
||||||
|
Nintendo logo that shows when you turn the Game Boy on. If no valid data is
|
||||||
|
found, this method will return NULL. */
|
||||||
|
const void* gb_first_rom(const void* data, size_t length);
|
||||||
|
|
||||||
|
/* Returns a pointer to the next Game Boy ROM in the data. If the location
|
||||||
|
where the next ROM would be does not contain a valid Nintendo logo at 0x104,
|
||||||
|
this method will return NULL. */
|
||||||
|
const void* gb_next_rom(const void* data, size_t length, const void* first_rom);
|
||||||
|
|
||||||
|
/* Returns a copy of the title from the ROM header. If buffer is NULL, the
|
||||||
|
string will be allocated in an internal 16-byte buffer which will be
|
||||||
|
overwritten later. If buffer is not NULL, the title will be copied to buffer,
|
||||||
|
and buffer will be returned. */
|
||||||
|
const char* gb_get_title(const void* rom, char* buffer);
|
445
source/goomba/goombasav.cpp
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/* goombasav.c - functions to handle Goomba / Goomba Color SRAM
|
||||||
|
|
||||||
|
last updated September 8, 2014
|
||||||
|
Copyright (C) 2014 libertyernie
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
https://github.com/libertyernie/goombasav
|
||||||
|
|
||||||
|
When compiling in Visual Studio, set all goombasav files to compile
|
||||||
|
as C++ code (Properties -> C/C++ -> Advanced -> Compile As.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "goombasav.h"
|
||||||
|
#include "minilzo-2.06/minilzo.h"
|
||||||
|
|
||||||
|
#define goomba_error(...) { sprintf(last_error, __VA_ARGS__); }
|
||||||
|
|
||||||
|
#define F16 little_endian_conv_16
|
||||||
|
#define F32 little_endian_conv_32
|
||||||
|
|
||||||
|
static const char* const sleeptxt[] = { "5min", "10min", "30min", "OFF" };
|
||||||
|
static const char* const brightxt[] = { "I", "II", "III", "IIII", "IIIII" };
|
||||||
|
|
||||||
|
static char last_error[256] = "No error has occured yet.";
|
||||||
|
static char goomba_strbuf[256];
|
||||||
|
|
||||||
|
const char* goomba_last_error() {
|
||||||
|
return (const char*)last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t goomba_set_last_error(const char* msg) {
|
||||||
|
size_t len = strnlen(msg, sizeof(last_error)-1);
|
||||||
|
memcpy(last_error, msg, len);
|
||||||
|
last_error[sizeof(last_error)-1] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For making a checksum of the compressed data.
|
||||||
|
// output_bytes is limited to 8 at maximum
|
||||||
|
uint64_t checksum_slow(const void* ptr, size_t length, int output_bytes) {
|
||||||
|
const unsigned char* p = (const unsigned char*)ptr;
|
||||||
|
uint64_t sum=0;
|
||||||
|
char* sumptr = (char*)∑
|
||||||
|
size_t j;
|
||||||
|
for (j=0;j<length;j++) {
|
||||||
|
int index = j%output_bytes;
|
||||||
|
sumptr[index] += *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t little_endian_conv_16(uint16_t value) {
|
||||||
|
if (*(uint16_t *)"\0\xff" < 0x100) {
|
||||||
|
uint16_t buffer;
|
||||||
|
((char*)&buffer)[0] = ((char*)&value)[1];
|
||||||
|
((char*)&buffer)[1] = ((char*)&value)[0];
|
||||||
|
return buffer;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t little_endian_conv_32(uint32_t value) {
|
||||||
|
if (*(uint16_t *)"\0\xff" < 0x100) {
|
||||||
|
uint32_t buffer;
|
||||||
|
((char*)&buffer)[0] = ((char*)&value)[3];
|
||||||
|
((char*)&buffer)[1] = ((char*)&value)[2];
|
||||||
|
((char*)&buffer)[2] = ((char*)&value)[1];
|
||||||
|
((char*)&buffer)[3] = ((char*)&value)[0];
|
||||||
|
return buffer;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configdata_misc_strings configdata_get_misc(char misc) {
|
||||||
|
configdata_misc_strings s;
|
||||||
|
s.sleep = sleeptxt[misc & 0x3];
|
||||||
|
s.autoload_state = ((misc & 0x10) >> 4) ? "ON" : "OFF";
|
||||||
|
s.gamma = brightxt[(misc & 0xE0) >> 5];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* stateheader_typestr(uint16_t type) {
|
||||||
|
switch (type) {
|
||||||
|
case GOOMBA_STATESAVE:
|
||||||
|
return "Savestate";
|
||||||
|
case GOOMBA_SRAMSAVE:
|
||||||
|
return "SRAM";
|
||||||
|
case GOOMBA_CONFIGSAVE:
|
||||||
|
return "Configuration";
|
||||||
|
case GOOMBA_PALETTE: // Used by Goomba Paletted
|
||||||
|
return "Palette";
|
||||||
|
default:
|
||||||
|
return "Unknown"; // Stateheaders with these types are rejected by stateheader_plausible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* stateheader_str(const stateheader* sh) {
|
||||||
|
int j = 0;
|
||||||
|
j += sprintf(goomba_strbuf + j, "size: %u\n", F16(sh->size));
|
||||||
|
j += sprintf(goomba_strbuf + j, "type: %s (%u)\n", stateheader_typestr(F16(sh->type)), F16(sh->type));
|
||||||
|
if (F16(sh->type) == GOOMBA_CONFIGSAVE) {
|
||||||
|
configdata* cd = (configdata*)sh;
|
||||||
|
j += sprintf(goomba_strbuf + j, "bordercolor: %u\n", cd->bordercolor);
|
||||||
|
j += sprintf(goomba_strbuf + j, "palettebank: %u\n", cd->palettebank);
|
||||||
|
configdata_misc_strings strs = configdata_get_misc(cd->misc);
|
||||||
|
j += sprintf(goomba_strbuf + j, "sleep: %s\n", strs.sleep);
|
||||||
|
j += sprintf(goomba_strbuf + j, "autoload state: %s\n", strs.autoload_state);
|
||||||
|
j += sprintf(goomba_strbuf + j, "gamma: %s\n", strs.gamma);
|
||||||
|
j += sprintf(goomba_strbuf + j, "rom checksum: %8X (0xE000-0xFFFF %s)\n", F32(cd->sram_checksum),
|
||||||
|
cd->sram_checksum != 0 ? "occupied" : "free");
|
||||||
|
} else {
|
||||||
|
j += sprintf(goomba_strbuf + j, "%scompressed_size: %u\n",
|
||||||
|
(F32(sh->uncompressed_size) < F16(sh->size) ? "" : "un"),
|
||||||
|
F32(sh->uncompressed_size));
|
||||||
|
j += sprintf(goomba_strbuf + j, "framecount: %u\n", F32(sh->framecount));
|
||||||
|
j += sprintf(goomba_strbuf + j, "rom checksum: %8X\n", F32(sh->checksum));
|
||||||
|
}
|
||||||
|
j += sprintf(goomba_strbuf + j, "title: %s", sh->title);
|
||||||
|
return goomba_strbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* stateheader_summary_str(const stateheader* sh) {
|
||||||
|
sprintf(goomba_strbuf, "%s: %s (%u b / %u uncomp)", stateheader_typestr(
|
||||||
|
F16(sh->type)), sh->title, F16(sh->size), F32(sh->uncompressed_size));
|
||||||
|
return goomba_strbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stateheader_plausible(const stateheader* sh) {
|
||||||
|
uint16_t type = F16(sh->type);
|
||||||
|
if (type < 0 || type == 3 || type == 4 || type > 5) return 0;
|
||||||
|
return F16(sh->size) >= sizeof(stateheader) && // check size (at least 48)
|
||||||
|
(F16(sh->type) == GOOMBA_CONFIGSAVE || sh->uncompressed_size != 0); // check uncompressed_size, but not for configsave
|
||||||
|
// when checking for whether something equals 0, endian conversion is not necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
stateheader* stateheader_advance(const stateheader* sh) {
|
||||||
|
if (!stateheader_plausible(sh)) return NULL;
|
||||||
|
|
||||||
|
uint16_t s = F16(sh->size);
|
||||||
|
char* c = (char*)sh;
|
||||||
|
c += s;
|
||||||
|
return (stateheader*)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
stateheader** stateheader_scan(const void* gba_data) {
|
||||||
|
// Do not edit gba_data!
|
||||||
|
// We are casting to non-const pointers so the client gets non-const pointers back.
|
||||||
|
const goomba_size_t psize = sizeof(stateheader*);
|
||||||
|
stateheader** headers = (stateheader**)malloc(psize * 64);
|
||||||
|
memset(headers, 0, psize * 64);
|
||||||
|
|
||||||
|
uint32_t* check = (uint32_t*)gba_data;
|
||||||
|
if (F32(*check) == GOOMBA_STATEID) check++;
|
||||||
|
|
||||||
|
stateheader* sh = (stateheader*)check;
|
||||||
|
int i = 0;
|
||||||
|
while (stateheader_plausible(sh) && i < 63) {
|
||||||
|
headers[i] = sh;
|
||||||
|
i++;
|
||||||
|
sh = stateheader_advance(sh);
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
stateheader* stateheader_for(const void* gba_data, const char* gbc_title) {
|
||||||
|
char title[0x10];
|
||||||
|
memcpy(title, gbc_title, 0x0F);
|
||||||
|
title[0x0F] = '\0';
|
||||||
|
stateheader* use_this = NULL;
|
||||||
|
stateheader** headers = stateheader_scan(gba_data);
|
||||||
|
int i;
|
||||||
|
for (i = 0; headers[i] != NULL; i++) {
|
||||||
|
if (strcmp(headers[i]->title, title) == 0 && F16(headers[i]->type) == GOOMBA_SRAMSAVE) {
|
||||||
|
use_this = headers[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(headers);
|
||||||
|
if (use_this == NULL) sprintf(last_error, "Could not find SRAM data for %s", title);
|
||||||
|
return use_this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses checksum_slow, and looks at the compressed data (not the header).
|
||||||
|
// output_bytes is limited to 8 at maximum
|
||||||
|
uint64_t goomba_compressed_data_checksum(const stateheader* sh, int output_bytes) {
|
||||||
|
return checksum_slow(sh+1, F16(sh->size) - sizeof(stateheader), output_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int goomba_is_sram(const void* data) {
|
||||||
|
return F32(*(uint32_t*)data) == GOOMBA_STATEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the 32-bit checksum (unsigned) in the configdata header, or -1 if
|
||||||
|
* stateheader_scan returns NULL due to an error. When using this function,
|
||||||
|
* first check if the value is less than 0, then (if not) cast to uint32_t.
|
||||||
|
*/
|
||||||
|
int64_t goomba_get_configdata_checksum_field(const void* gba_data) {
|
||||||
|
// todo fix
|
||||||
|
stateheader** headers = stateheader_scan(gba_data);
|
||||||
|
if (headers == NULL) return -1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; headers[i] != NULL; i++) {
|
||||||
|
if (F16(headers[i]->type) == GOOMBA_CONFIGSAVE) {
|
||||||
|
// found configdata
|
||||||
|
const configdata* cd = (configdata*)headers[i];
|
||||||
|
free(headers);
|
||||||
|
return F32(cd->sram_checksum); // 0 = clean, postitive = unclean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(headers);
|
||||||
|
return -1; // not sure when this would happen
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goomba_cleanup(const void* gba_data_param) {
|
||||||
|
char gba_data[GOOMBA_COLOR_SRAM_SIZE]; // on stack - do not need to free
|
||||||
|
memcpy(gba_data, gba_data_param, GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
|
||||||
|
stateheader** headers = stateheader_scan(gba_data);
|
||||||
|
if (headers == NULL) return NULL;
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; headers[i] != NULL; i++) {
|
||||||
|
if (F16(headers[i]->type) == GOOMBA_CONFIGSAVE) {
|
||||||
|
// found configdata
|
||||||
|
configdata* cd = (configdata*)headers[i];
|
||||||
|
const uint32_t checksum = F32(cd->sram_checksum);
|
||||||
|
for (j = 0; headers[j] != NULL; j++) {
|
||||||
|
stateheader* sh = headers[j];
|
||||||
|
if (F16(sh->type) == GOOMBA_SRAMSAVE && F32(sh->checksum) == checksum) {
|
||||||
|
// found stateheader
|
||||||
|
free(headers); // so make sure we return something before the loop goes around again!!
|
||||||
|
|
||||||
|
cd->sram_checksum = 0; // because we do this here, goomba_new_sav should not complain about an unclean file
|
||||||
|
|
||||||
|
char gbc_data[GOOMBA_COLOR_SRAM_SIZE - GOOMBA_COLOR_AVAILABLE_SIZE];
|
||||||
|
memcpy(gbc_data,
|
||||||
|
gba_data + GOOMBA_COLOR_AVAILABLE_SIZE,
|
||||||
|
sizeof(gbc_data)); // Extract GBC data at 0xe000 to an array
|
||||||
|
|
||||||
|
char* new_gba_data = goomba_new_sav(gba_data, sh, gbc_data, sizeof(gbc_data));
|
||||||
|
if (new_gba_data != NULL) memset(new_gba_data + GOOMBA_COLOR_AVAILABLE_SIZE, 0, sizeof(gbc_data));
|
||||||
|
return new_gba_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(headers);
|
||||||
|
return (char*)gba_data_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* goomba_extract(const void* gba_data, const stateheader* header_ptr, goomba_size_t* size_output) {
|
||||||
|
const stateheader* sh = (const stateheader*)header_ptr;
|
||||||
|
|
||||||
|
if (F16(sh->type) != GOOMBA_SRAMSAVE) {
|
||||||
|
goomba_error("Error: this program can only extract SRAM data.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t ck = goomba_get_configdata_checksum_field(gba_data);
|
||||||
|
if (ck < 0) {
|
||||||
|
return NULL;
|
||||||
|
} else if (ck == F32(sh->checksum)) {
|
||||||
|
goomba_error("File is unclean - run goomba_cleanup before trying to extract SRAM, or you might get old data\n");
|
||||||
|
return NULL;
|
||||||
|
} else if (ck != 0) {
|
||||||
|
fprintf(stderr, "File is unclean, but it shouldn't affect retrieval of the data you asked for\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
lzo_uint compressed_size = F16(sh->size) - sizeof(stateheader);
|
||||||
|
lzo_uint output_size = 32768;
|
||||||
|
const unsigned char* compressed_data = (unsigned char*)header_ptr + sizeof(stateheader);
|
||||||
|
unsigned char* uncompressed_data = (unsigned char*)malloc(output_size);
|
||||||
|
int r = lzo1x_decompress_safe(compressed_data, compressed_size,
|
||||||
|
uncompressed_data, &output_size,
|
||||||
|
(void*)NULL);
|
||||||
|
//fprintf(stderr, "Actual uncompressed size: %lu\n", output_size);
|
||||||
|
if (r == LZO_E_INPUT_NOT_CONSUMED) {
|
||||||
|
//goomba_error("Warning: input not fully used. Double-check the result to make sure it works.\n");
|
||||||
|
} else if (r < 0) {
|
||||||
|
goomba_error("Cannot decompress data (lzoconf.h error code %d).\n", r);
|
||||||
|
free(uncompressed_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*size_output = output_size;
|
||||||
|
return uncompressed_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
goomba_size_t copy_until_invalid_header(void* dest, const stateheader* src_param) {
|
||||||
|
const void* src = src_param;
|
||||||
|
goomba_size_t bytes_copied = 0;
|
||||||
|
while (1) {
|
||||||
|
const stateheader* sh = (const stateheader*)src;
|
||||||
|
if (!stateheader_plausible(sh)) break;
|
||||||
|
|
||||||
|
memcpy(dest, src, F16(sh->size));
|
||||||
|
|
||||||
|
src = (char*)src + F16(sh->size);
|
||||||
|
dest = (char*)dest + F16(sh->size);
|
||||||
|
bytes_copied += F16(sh->size);
|
||||||
|
}
|
||||||
|
memcpy(dest, src, sizeof(stateheader)); // copy "footer"
|
||||||
|
return bytes_copied + sizeof(stateheader);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goomba_new_sav(const void* gba_data, const void* gba_header, const void* gbc_sram, goomba_size_t gbc_length) {
|
||||||
|
unsigned char* gba_header_ptr = (unsigned char*)gba_header;
|
||||||
|
stateheader* sh = (stateheader*)gba_header_ptr;
|
||||||
|
|
||||||
|
int64_t ck = goomba_get_configdata_checksum_field(gba_data);
|
||||||
|
if (ck < 0) {
|
||||||
|
return NULL;
|
||||||
|
} else if (ck == F32(sh->checksum)) {
|
||||||
|
// have to clean file
|
||||||
|
goomba_error("File is unclean - run goomba_cleanup before trying to replace SRAM, or your new data might get overwritten");
|
||||||
|
return NULL;
|
||||||
|
} else if (ck != 0) {
|
||||||
|
fprintf(stderr, "File is unclean, but it shouldn't affect replacement of the data you asked for\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (F16(sh->type) != GOOMBA_SRAMSAVE) {
|
||||||
|
goomba_error("Error - This program cannot replace non-SRAM data.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sh->uncompressed_size is valid for Goomba Color.
|
||||||
|
// For Goomba, it's actually compressed size (and will be less than sh->size).
|
||||||
|
goomba_size_t uncompressed_size;
|
||||||
|
if (F16(sh->size) > F32(sh->uncompressed_size)) {
|
||||||
|
// Uncompress to a temporary location, just so we can see how big it is
|
||||||
|
goomba_size_t output;
|
||||||
|
void* dump = goomba_extract(gba_data, sh, &output);
|
||||||
|
if (dump == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
free(dump);
|
||||||
|
uncompressed_size = output;
|
||||||
|
} else {
|
||||||
|
// Goomba Color header - use size from there
|
||||||
|
uncompressed_size = F32(sh->uncompressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gbc_length < uncompressed_size) {
|
||||||
|
goomba_error("Error: the length of the GBC data (%u) is too short - expected %u bytes.\n",
|
||||||
|
gbc_length, uncompressed_size);
|
||||||
|
return NULL;
|
||||||
|
} else if (gbc_length - 4 == uncompressed_size) {
|
||||||
|
goomba_error("Note: RTC data (TGB_Dual format) will not be copied\n");
|
||||||
|
} else if (gbc_length - 44 == uncompressed_size) {
|
||||||
|
goomba_error("Note: RTC data (old VBA format) will not be copied\n");
|
||||||
|
} else if (gbc_length - 48 == uncompressed_size) {
|
||||||
|
goomba_error("Note: RTC data (new VBA format) will not be copied\n");
|
||||||
|
} else if (gbc_length > uncompressed_size) {
|
||||||
|
goomba_error("Warning: unknown data at end of GBC save file - only first %u bytes will be used\n", uncompressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (F16(sh->type) != GOOMBA_SRAMSAVE) {
|
||||||
|
goomba_error("The data at gba_header is not SRAM data.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* const goomba_new_sav = (char*)malloc(GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
memset(goomba_new_sav, 0, GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
char* working = goomba_new_sav; // will be incremented throughout
|
||||||
|
|
||||||
|
goomba_size_t before_header = (char*)gba_header - (char*)gba_data;
|
||||||
|
// copy anything before stateheader
|
||||||
|
memcpy(goomba_new_sav, gba_data, before_header);
|
||||||
|
working += before_header;
|
||||||
|
// copy stateheader
|
||||||
|
memcpy(working, sh, sizeof(stateheader));
|
||||||
|
stateheader* new_sh = (stateheader*)working;
|
||||||
|
working += sizeof(stateheader);
|
||||||
|
|
||||||
|
// backup data that comes after this header
|
||||||
|
unsigned char* backup = (unsigned char*)malloc(GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
goomba_size_t backup_len = copy_until_invalid_header(backup, (stateheader*)(gba_header_ptr + F16(sh->size)));
|
||||||
|
|
||||||
|
// compress gbc sram
|
||||||
|
lzo_uint compressed_size;
|
||||||
|
unsigned char* dest = (unsigned char*)working;
|
||||||
|
void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS);
|
||||||
|
lzo1x_1_compress((const unsigned char*)gbc_sram, uncompressed_size,
|
||||||
|
dest, &compressed_size,
|
||||||
|
wrkmem);
|
||||||
|
free(wrkmem);
|
||||||
|
working += compressed_size;
|
||||||
|
//fprintf(stderr, "Compressed %u bytes (compressed size: %lu)\n", uncompressed_size, compressed_size);
|
||||||
|
|
||||||
|
if (F16(sh->size) > F32(sh->uncompressed_size)) {
|
||||||
|
// Goomba header (not Goomba Color)
|
||||||
|
new_sh->uncompressed_size = F32(compressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_sh->size = F16((uint16_t)(compressed_size + sizeof(stateheader)));
|
||||||
|
// pad to 4 bytes!
|
||||||
|
// if I don't do this, goomba color might not load the palette settings, or seemingly 'forget' them later
|
||||||
|
// btw, the settings are stored in the configdata struct defined in goombasav.h
|
||||||
|
uint16_t s = F16(new_sh->size);
|
||||||
|
while (s % 4 != 0) {
|
||||||
|
*working = 0;
|
||||||
|
working++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
new_sh->size = F16(s);
|
||||||
|
|
||||||
|
goomba_size_t used = working - goomba_new_sav;
|
||||||
|
if (used + backup_len > GOOMBA_COLOR_AVAILABLE_SIZE) {
|
||||||
|
goomba_error("Not enough room in file for the new save data (0xe000-0xffff must be kept free, I think)\n");
|
||||||
|
free(backup);
|
||||||
|
free(goomba_new_sav);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// restore the backup - just assume we have enough space
|
||||||
|
memcpy(working, backup, backup_len);
|
||||||
|
free(backup);
|
||||||
|
|
||||||
|
// restore data from 0xe000 to 0xffff
|
||||||
|
memcpy(goomba_new_sav + GOOMBA_COLOR_AVAILABLE_SIZE,
|
||||||
|
(char*)gba_data + GOOMBA_COLOR_AVAILABLE_SIZE,
|
||||||
|
GOOMBA_COLOR_SRAM_SIZE - GOOMBA_COLOR_AVAILABLE_SIZE);
|
||||||
|
|
||||||
|
return goomba_new_sav;
|
||||||
|
}
|
184
source/goomba/goombasav.h
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/* goombasav.h - functions to handle Goomba / Goomba Color SRAM
|
||||||
|
|
||||||
|
last updated July 3, 2014
|
||||||
|
Copyright (C) 2014 libertyernie
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
https://github.com/libertyernie/goombasav
|
||||||
|
|
||||||
|
When compiling in Visual Studio, set all goombasav files to compile
|
||||||
|
as C++ code (Properties -> C/C++ -> Advanced -> Compile As.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GOOMBASAV_H
|
||||||
|
#define __GOOMBASAV_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#define GOOMBA_COLOR_SRAM_SIZE 65536
|
||||||
|
#define GOOMBA_COLOR_AVAILABLE_SIZE 57344
|
||||||
|
#define GOOMBA_STATEID 0x57a731d8
|
||||||
|
#define GOOMBA_STATESAVE 0
|
||||||
|
#define GOOMBA_SRAMSAVE 1
|
||||||
|
#define GOOMBA_CONFIGSAVE 2
|
||||||
|
#define GOOMBA_PALETTE 5
|
||||||
|
|
||||||
|
typedef uint32_t goomba_size_t; // want a consistent size for printf. This is an alias for uint32_t, but this makes it clear that we're counting the size of something.
|
||||||
|
|
||||||
|
/* 16-bit and 32-bit values in the stateheader are stored as little endian
|
||||||
|
(native to the GBA's ARM chip as well as x86 processors.) Use this function
|
||||||
|
after getting or before setting a value if your code might run on a big-endian
|
||||||
|
processor (e.g. PowerPC.) */
|
||||||
|
uint16_t little_endian_conv_16(uint16_t value);
|
||||||
|
|
||||||
|
/* 16-bit and 32-bit values in the stateheader are stored as little endian
|
||||||
|
(native to the GBA's ARM chip as well as x86 processors.) Use this function
|
||||||
|
after getting or before setting a value if your code might run on a big-endian
|
||||||
|
processor (e.g. PowerPC.) */
|
||||||
|
uint32_t little_endian_conv_32(uint32_t value);
|
||||||
|
|
||||||
|
typedef struct { //(modified stateheader)
|
||||||
|
uint16_t size;
|
||||||
|
uint16_t type; //=CONFIGSAVE
|
||||||
|
char bordercolor;
|
||||||
|
char palettebank;
|
||||||
|
char misc;
|
||||||
|
char reserved3;
|
||||||
|
uint32_t sram_checksum; //checksum of rom using SRAM e000-ffff
|
||||||
|
uint32_t zero; //=0
|
||||||
|
char reserved4[32]; //="CFG"
|
||||||
|
} configdata;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t size; //header+data
|
||||||
|
uint16_t type; //=STATESAVE or SRAMSAVE
|
||||||
|
uint32_t uncompressed_size;
|
||||||
|
uint32_t framecount;
|
||||||
|
uint32_t checksum;
|
||||||
|
char title[32];
|
||||||
|
} stateheader;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* sleep;
|
||||||
|
const char* autoload_state;
|
||||||
|
const char* gamma;
|
||||||
|
} configdata_misc_strings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last error encountered by goombasav (for functions that return
|
||||||
|
* NULL on error.) This string is stored statically by goombasav and its
|
||||||
|
* contents may change over time.
|
||||||
|
*/
|
||||||
|
const char* goomba_last_error();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the string buffer used by goomba_last_error to a custom value. If the
|
||||||
|
* input string is too long, the resulting goomba_last_error string will be
|
||||||
|
* truncated.
|
||||||
|
* Returns the number of bytes copied to the buffer (at present, the maximum
|
||||||
|
* is 255.)
|
||||||
|
*/
|
||||||
|
size_t goomba_set_last_error(const char* msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a struct containing pointers to three static strings (which do not
|
||||||
|
* need to be deallocated.)
|
||||||
|
*/
|
||||||
|
configdata_misc_strings configdata_get_misc(char misc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a multi-line description string that includes all parameters of the
|
||||||
|
* given stateheader or configdata structure.
|
||||||
|
* This string is stored in a static character buffer, and subsequent calls to
|
||||||
|
* stateheader_str or stateheader_summary_str will overwrite this buffer.
|
||||||
|
*/
|
||||||
|
const char* stateheader_str(const stateheader* sh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a one-line summary string displaying the size and title of the
|
||||||
|
* stateheader or configdata structure.
|
||||||
|
* This string is stored in a static character buffer, and subsequent calls to
|
||||||
|
* stateheader_str or stateheader_summary_str will overwrite this buffer.
|
||||||
|
*/
|
||||||
|
const char* stateheader_summary_str(const stateheader* sh);
|
||||||
|
|
||||||
|
int stateheader_plausible(const stateheader* sh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When given a pointer to a stateheader, returns a pointer to where the next
|
||||||
|
* stateheader will be located (if any). Use stateheader_plausible to
|
||||||
|
* determine if there really is a header at this location.
|
||||||
|
*
|
||||||
|
* If stateheader_plausible determines that the input is not a valid
|
||||||
|
* stateheader, NULL will be returned.
|
||||||
|
*/
|
||||||
|
stateheader* stateheader_advance(const stateheader* sh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans for valid stateheaders and allocates an array to store them. The array
|
||||||
|
* will have a capacity of 64, and any difference between that
|
||||||
|
* and the number of headers found will be filled with NULL entries. The last
|
||||||
|
* entry (array[63]) is guaranteed to be NULL.
|
||||||
|
* NOTE: the gba_data parameter can point to a valid header, or to a sequence
|
||||||
|
* equal to GOOMBA_STATEID immediately before a valid header.
|
||||||
|
*/
|
||||||
|
stateheader** stateheader_scan(const void* gba_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stateheader in gba_data with the title field = gbc_title,
|
||||||
|
* or NULL if there is none. Only the first 15 bytes of gbc_title will be
|
||||||
|
* used in the comparison.
|
||||||
|
*/
|
||||||
|
stateheader* stateheader_for(const void* gba_data, const char* gbc_title_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given data starts with GOOMBA_STATEID (little endian.)
|
||||||
|
*/
|
||||||
|
int goomba_is_sram(const void* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a hash of the compressed data that comes after the given header,
|
||||||
|
* using output_bytes bytes. A three-byte hash can be displayed as a color to
|
||||||
|
* give visual feedback of a change in the data. The maximum of output_bytes is
|
||||||
|
* sizeof(int).
|
||||||
|
*/
|
||||||
|
uint64_t goomba_compressed_data_checksum(const stateheader* sh, int output_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there is save data in 0xe000-0xffff (as signaled by the configdata),
|
||||||
|
* this function compresses it to where it's supposed to go. In the event that
|
||||||
|
* the data passed in is already clean, the same pointer will be returned.
|
||||||
|
* NULL will be returned if an error occurs.
|
||||||
|
*
|
||||||
|
* The given pointer must be at least GOOMBA_COLOR_SRAM_SIZE bytes in length.
|
||||||
|
* If it is longer, any information after GOOMBA_COLOR_SRAM_SIZE bytes will be
|
||||||
|
* ignored.
|
||||||
|
*/
|
||||||
|
char* goomba_cleanup(const void* gba_data_param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates memory to store the uncompressed GB/GBC save file extracted from
|
||||||
|
* the Goomba Color save file stored in header_ptr, or returns NULL if the
|
||||||
|
* decompression failed.
|
||||||
|
*/
|
||||||
|
void* goomba_extract(const void* gba_data, const stateheader* header_ptr, goomba_size_t* size_output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies data from the source (which must point to a valid stateheader or
|
||||||
|
* configdata) to dest, up to and including the first 48 bytes that do not
|
||||||
|
* constitute a valid header.
|
||||||
|
*/
|
||||||
|
char* goomba_new_sav(const void* gba_data, const void* gba_header, const void* gbc_sram, goomba_size_t gbc_length);
|
||||||
|
|
||||||
|
#endif
|
339
source/goomba/minilzo-2.06/COPYING
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
124
source/goomba/minilzo-2.06/README.LZO
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
============================================================================
|
||||||
|
miniLZO -- mini subset of the LZO real-time data compression library
|
||||||
|
============================================================================
|
||||||
|
|
||||||
|
Author : Markus Franz Xaver Johannes Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
http://www.oberhumer.com/opensource/lzo/
|
||||||
|
Version : 2.06
|
||||||
|
Date : 12 Aug 2011
|
||||||
|
|
||||||
|
I've created miniLZO for projects where it is inconvenient to
|
||||||
|
include (or require) the full LZO source code just because you
|
||||||
|
want to add a little bit of data compression to your application.
|
||||||
|
|
||||||
|
miniLZO implements the LZO1X-1 compressor and both the standard and
|
||||||
|
safe LZO1X decompressor. Apart from fast compression it also useful
|
||||||
|
for situations where you want to use pre-compressed data files (which
|
||||||
|
must have been compressed with LZO1X-999).
|
||||||
|
|
||||||
|
miniLZO consists of one C source file and three header files:
|
||||||
|
minilzo.c
|
||||||
|
minilzo.h, lzoconf.h, lzodefs.h
|
||||||
|
|
||||||
|
To use miniLZO just copy these files into your source directory, add
|
||||||
|
minilzo.c to your Makefile and #include minilzo.h from your program.
|
||||||
|
Note: you also must distribute this file ('README.LZO') with your project.
|
||||||
|
|
||||||
|
minilzo.o compiles to about 6 KiB (using gcc or Visual C on an i386), and
|
||||||
|
the sources are about 30 KiB when packed with zip - so there's no more
|
||||||
|
excuse that your application doesn't support data compression :-)
|
||||||
|
|
||||||
|
For more information, documentation, example programs and other support
|
||||||
|
files (like Makefiles and build scripts) please download the full LZO
|
||||||
|
package from
|
||||||
|
http://www.oberhumer.com/opensource/lzo/
|
||||||
|
|
||||||
|
Have fun,
|
||||||
|
Markus
|
||||||
|
|
||||||
|
|
||||||
|
P.S. minilzo.c is generated automatically from the LZO sources and
|
||||||
|
therefore functionality is completely identical
|
||||||
|
|
||||||
|
|
||||||
|
Appendix A: building miniLZO
|
||||||
|
----------------------------
|
||||||
|
miniLZO is written such a way that it should compile and run
|
||||||
|
out-of-the-box on most machines.
|
||||||
|
|
||||||
|
If you are running on a very unusual architecture and lzo_init() fails then
|
||||||
|
you should first recompile with '-DLZO_DEBUG' to see what causes the failure.
|
||||||
|
The most probable case is something like 'sizeof(void *) != sizeof(size_t)'.
|
||||||
|
After identifying the problem you can compile by adding some defines
|
||||||
|
like '-DSIZEOF_VOID_P=8' to your Makefile.
|
||||||
|
|
||||||
|
The best solution is (of course) using Autoconf - if your project uses
|
||||||
|
Autoconf anyway just add '-DMINILZO_HAVE_CONFIG_H' to your compiler
|
||||||
|
flags when compiling minilzo.c. See the LZO distribution for an example
|
||||||
|
how to set up configure.ac.
|
||||||
|
|
||||||
|
|
||||||
|
Appendix B: list of public functions available in miniLZO
|
||||||
|
---------------------------------------------------------
|
||||||
|
Library initialization
|
||||||
|
lzo_init()
|
||||||
|
|
||||||
|
Compression
|
||||||
|
lzo1x_1_compress()
|
||||||
|
|
||||||
|
Decompression
|
||||||
|
lzo1x_decompress()
|
||||||
|
lzo1x_decompress_safe()
|
||||||
|
|
||||||
|
Checksum functions
|
||||||
|
lzo_adler32()
|
||||||
|
|
||||||
|
Version functions
|
||||||
|
lzo_version()
|
||||||
|
lzo_version_string()
|
||||||
|
lzo_version_date()
|
||||||
|
|
||||||
|
Portable (but slow) string functions
|
||||||
|
lzo_memcmp()
|
||||||
|
lzo_memcpy()
|
||||||
|
lzo_memmove()
|
||||||
|
lzo_memset()
|
||||||
|
|
||||||
|
|
||||||
|
Appendix C: suggested macros for 'configure.ac' when using Autoconf
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Checks for typedefs and structures
|
||||||
|
AC_CHECK_TYPE(ptrdiff_t,long)
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_CHECK_SIZEOF(short)
|
||||||
|
AC_CHECK_SIZEOF(int)
|
||||||
|
AC_CHECK_SIZEOF(long)
|
||||||
|
AC_CHECK_SIZEOF(long long)
|
||||||
|
AC_CHECK_SIZEOF(__int64)
|
||||||
|
AC_CHECK_SIZEOF(void *)
|
||||||
|
AC_CHECK_SIZEOF(size_t)
|
||||||
|
AC_CHECK_SIZEOF(ptrdiff_t)
|
||||||
|
|
||||||
|
Checks for compiler characteristics
|
||||||
|
AC_C_CONST
|
||||||
|
|
||||||
|
Checks for library functions
|
||||||
|
AC_CHECK_FUNCS(memcmp memcpy memmove memset)
|
||||||
|
|
||||||
|
|
||||||
|
Appendix D: Copyright
|
||||||
|
---------------------
|
||||||
|
LZO and miniLZO are Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||||
|
Markus Franz Xaver Oberhumer <markus@oberhumer.com>.
|
||||||
|
|
||||||
|
LZO and miniLZO are distributed under the terms of the GNU General
|
||||||
|
Public License (GPL). See the file COPYING.
|
||||||
|
|
||||||
|
Special licenses for commercial and other applications which
|
||||||
|
are not willing to accept the GNU General Public License
|
||||||
|
are available by contacting the author.
|
||||||
|
|
||||||
|
|
446
source/goomba/minilzo-2.06/lzoconf.h
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
/* lzoconf.h -- configuration of the LZO data compression library
|
||||||
|
|
||||||
|
This file is part of the LZO real-time data compression library.
|
||||||
|
|
||||||
|
Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
The LZO library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The LZO library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the LZO library; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
http://www.oberhumer.com/opensource/lzo/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LZOCONF_H_INCLUDED
|
||||||
|
#define __LZOCONF_H_INCLUDED 1
|
||||||
|
|
||||||
|
#define LZO_VERSION 0x2060
|
||||||
|
#define LZO_VERSION_STRING "2.06"
|
||||||
|
#define LZO_VERSION_DATE "Aug 12 2011"
|
||||||
|
|
||||||
|
/* internal Autoconf configuration file - only used when building LZO */
|
||||||
|
#if defined(LZO_HAVE_CONFIG_H)
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// LZO requires a conforming <limits.h>
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
|
||||||
|
# error "invalid CHAR_BIT"
|
||||||
|
#endif
|
||||||
|
#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
|
||||||
|
# error "check your compiler installation"
|
||||||
|
#endif
|
||||||
|
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
|
||||||
|
# error "your limits.h macros are broken"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get OS and architecture defines */
|
||||||
|
#ifndef __LZODEFS_H_INCLUDED
|
||||||
|
#include "lzodefs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// some core defines
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(LZO_UINT32_C)
|
||||||
|
# if (UINT_MAX < LZO_0xffffffffL)
|
||||||
|
# define LZO_UINT32_C(c) c ## UL
|
||||||
|
# else
|
||||||
|
# define LZO_UINT32_C(c) ((c) + 0U)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* memory checkers */
|
||||||
|
#if !defined(__LZO_CHECKER)
|
||||||
|
# if defined(__BOUNDS_CHECKING_ON)
|
||||||
|
# define __LZO_CHECKER 1
|
||||||
|
# elif defined(__CHECKER__)
|
||||||
|
# define __LZO_CHECKER 1
|
||||||
|
# elif defined(__INSURE__)
|
||||||
|
# define __LZO_CHECKER 1
|
||||||
|
# elif defined(__PURIFY__)
|
||||||
|
# define __LZO_CHECKER 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// integral and pointer types
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* lzo_uint should match size_t */
|
||||||
|
#if !defined(LZO_UINT_MAX)
|
||||||
|
# if defined(LZO_ABI_LLP64) /* WIN64 */
|
||||||
|
# if defined(LZO_OS_WIN64)
|
||||||
|
typedef unsigned __int64 lzo_uint;
|
||||||
|
typedef __int64 lzo_int;
|
||||||
|
# else
|
||||||
|
typedef unsigned long long lzo_uint;
|
||||||
|
typedef long long lzo_int;
|
||||||
|
# endif
|
||||||
|
# define LZO_UINT_MAX 0xffffffffffffffffull
|
||||||
|
# define LZO_INT_MAX 9223372036854775807LL
|
||||||
|
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
|
||||||
|
# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */
|
||||||
|
typedef unsigned int lzo_uint;
|
||||||
|
typedef int lzo_int;
|
||||||
|
# define LZO_UINT_MAX UINT_MAX
|
||||||
|
# define LZO_INT_MAX INT_MAX
|
||||||
|
# define LZO_INT_MIN INT_MIN
|
||||||
|
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||||
|
typedef unsigned long lzo_uint;
|
||||||
|
typedef long lzo_int;
|
||||||
|
# define LZO_UINT_MAX ULONG_MAX
|
||||||
|
# define LZO_INT_MAX LONG_MAX
|
||||||
|
# define LZO_INT_MIN LONG_MIN
|
||||||
|
# else
|
||||||
|
# error "lzo_uint"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Integral types with 32 bits or more. */
|
||||||
|
#if !defined(LZO_UINT32_MAX)
|
||||||
|
# if (UINT_MAX >= LZO_0xffffffffL)
|
||||||
|
typedef unsigned int lzo_uint32;
|
||||||
|
typedef int lzo_int32;
|
||||||
|
# define LZO_UINT32_MAX UINT_MAX
|
||||||
|
# define LZO_INT32_MAX INT_MAX
|
||||||
|
# define LZO_INT32_MIN INT_MIN
|
||||||
|
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||||
|
typedef unsigned long lzo_uint32;
|
||||||
|
typedef long lzo_int32;
|
||||||
|
# define LZO_UINT32_MAX ULONG_MAX
|
||||||
|
# define LZO_INT32_MAX LONG_MAX
|
||||||
|
# define LZO_INT32_MIN LONG_MIN
|
||||||
|
# else
|
||||||
|
# error "lzo_uint32"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Integral types with exactly 64 bits. */
|
||||||
|
#if !defined(LZO_UINT64_MAX)
|
||||||
|
# if (LZO_UINT_MAX >= LZO_0xffffffffL)
|
||||||
|
# if ((((LZO_UINT_MAX) >> 31) >> 31) == 3)
|
||||||
|
# define lzo_uint64 lzo_uint
|
||||||
|
# define lzo_int64 lzo_int
|
||||||
|
# define LZO_UINT64_MAX LZO_UINT_MAX
|
||||||
|
# define LZO_INT64_MAX LZO_INT_MAX
|
||||||
|
# define LZO_INT64_MIN LZO_INT_MIN
|
||||||
|
# endif
|
||||||
|
# elif (ULONG_MAX >= LZO_0xffffffffL)
|
||||||
|
# if ((((ULONG_MAX) >> 31) >> 31) == 3)
|
||||||
|
typedef unsigned long lzo_uint64;
|
||||||
|
typedef long lzo_int64;
|
||||||
|
# define LZO_UINT64_MAX ULONG_MAX
|
||||||
|
# define LZO_INT64_MAX LONG_MAX
|
||||||
|
# define LZO_INT64_MIN LONG_MIN
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The larger type of lzo_uint and lzo_uint32. */
|
||||||
|
#if (LZO_UINT_MAX >= LZO_UINT32_MAX)
|
||||||
|
# define lzo_xint lzo_uint
|
||||||
|
#else
|
||||||
|
# define lzo_xint lzo_uint32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Memory model that allows to access memory at offsets of lzo_uint. */
|
||||||
|
#if !defined(__LZO_MMODEL)
|
||||||
|
# if (LZO_UINT_MAX <= UINT_MAX)
|
||||||
|
# define __LZO_MMODEL /*empty*/
|
||||||
|
# elif defined(LZO_HAVE_MM_HUGE_PTR)
|
||||||
|
# define __LZO_MMODEL_HUGE 1
|
||||||
|
# define __LZO_MMODEL __huge
|
||||||
|
# else
|
||||||
|
# define __LZO_MMODEL /*empty*/
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* no typedef here because of const-pointer issues */
|
||||||
|
#define lzo_bytep unsigned char __LZO_MMODEL *
|
||||||
|
#define lzo_charp char __LZO_MMODEL *
|
||||||
|
#define lzo_voidp void __LZO_MMODEL *
|
||||||
|
#define lzo_shortp short __LZO_MMODEL *
|
||||||
|
#define lzo_ushortp unsigned short __LZO_MMODEL *
|
||||||
|
#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
|
||||||
|
#define lzo_int32p lzo_int32 __LZO_MMODEL *
|
||||||
|
#if defined(LZO_UINT64_MAX)
|
||||||
|
#define lzo_uint64p lzo_uint64 __LZO_MMODEL *
|
||||||
|
#define lzo_int64p lzo_int64 __LZO_MMODEL *
|
||||||
|
#endif
|
||||||
|
#define lzo_uintp lzo_uint __LZO_MMODEL *
|
||||||
|
#define lzo_intp lzo_int __LZO_MMODEL *
|
||||||
|
#define lzo_xintp lzo_xint __LZO_MMODEL *
|
||||||
|
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
|
||||||
|
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
|
||||||
|
/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
|
||||||
|
#define lzo_byte unsigned char __LZO_MMODEL
|
||||||
|
|
||||||
|
typedef int lzo_bool;
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// function types
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* name mangling */
|
||||||
|
#if !defined(__LZO_EXTERN_C)
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define __LZO_EXTERN_C extern "C"
|
||||||
|
# else
|
||||||
|
# define __LZO_EXTERN_C extern
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* calling convention */
|
||||||
|
#if !defined(__LZO_CDECL)
|
||||||
|
# define __LZO_CDECL __lzo_cdecl
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DLL export information */
|
||||||
|
#if !defined(__LZO_EXPORT1)
|
||||||
|
# define __LZO_EXPORT1 /*empty*/
|
||||||
|
#endif
|
||||||
|
#if !defined(__LZO_EXPORT2)
|
||||||
|
# define __LZO_EXPORT2 /*empty*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __cdecl calling convention for public C and assembly functions */
|
||||||
|
#if !defined(LZO_PUBLIC)
|
||||||
|
# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
|
||||||
|
#endif
|
||||||
|
#if !defined(LZO_EXTERN)
|
||||||
|
# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
|
||||||
|
#endif
|
||||||
|
#if !defined(LZO_PRIVATE)
|
||||||
|
# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* function types */
|
||||||
|
typedef int
|
||||||
|
(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem );
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem );
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem );
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem,
|
||||||
|
const lzo_bytep dict, lzo_uint dict_len );
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem,
|
||||||
|
const lzo_bytep dict, lzo_uint dict_len );
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback interface. Currently only the progress indicator ("nprogress")
|
||||||
|
* is used, but this may change in a future release. */
|
||||||
|
|
||||||
|
struct lzo_callback_t;
|
||||||
|
typedef struct lzo_callback_t lzo_callback_t;
|
||||||
|
#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
|
||||||
|
|
||||||
|
/* malloc & free function types */
|
||||||
|
typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
|
||||||
|
(lzo_callback_p self, lzo_uint items, lzo_uint size);
|
||||||
|
typedef void (__LZO_CDECL *lzo_free_func_t)
|
||||||
|
(lzo_callback_p self, lzo_voidp ptr);
|
||||||
|
|
||||||
|
/* a progress indicator callback function */
|
||||||
|
typedef void (__LZO_CDECL *lzo_progress_func_t)
|
||||||
|
(lzo_callback_p, lzo_uint, lzo_uint, int);
|
||||||
|
|
||||||
|
struct lzo_callback_t
|
||||||
|
{
|
||||||
|
/* custom allocators (set to 0 to disable) */
|
||||||
|
lzo_alloc_func_t nalloc; /* [not used right now] */
|
||||||
|
lzo_free_func_t nfree; /* [not used right now] */
|
||||||
|
|
||||||
|
/* a progress indicator callback function (set to 0 to disable) */
|
||||||
|
lzo_progress_func_t nprogress;
|
||||||
|
|
||||||
|
/* NOTE: the first parameter "self" of the nalloc/nfree/nprogress
|
||||||
|
* callbacks points back to this struct, so you are free to store
|
||||||
|
* some extra info in the following variables. */
|
||||||
|
lzo_voidp user1;
|
||||||
|
lzo_xint user2;
|
||||||
|
lzo_xint user3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// error codes and prototypes
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* Error codes for the compression/decompression functions. Negative
|
||||||
|
* values are errors, positive values will be used for special but
|
||||||
|
* normal events.
|
||||||
|
*/
|
||||||
|
#define LZO_E_OK 0
|
||||||
|
#define LZO_E_ERROR (-1)
|
||||||
|
#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */
|
||||||
|
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
|
||||||
|
#define LZO_E_INPUT_OVERRUN (-4)
|
||||||
|
#define LZO_E_OUTPUT_OVERRUN (-5)
|
||||||
|
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
|
||||||
|
#define LZO_E_EOF_NOT_FOUND (-7)
|
||||||
|
#define LZO_E_INPUT_NOT_CONSUMED (-8)
|
||||||
|
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
|
||||||
|
#define LZO_E_INVALID_ARGUMENT (-10)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef lzo_sizeof_dict_t
|
||||||
|
# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* lzo_init() should be the first function you call.
|
||||||
|
* Check the return code !
|
||||||
|
*
|
||||||
|
* lzo_init() is a macro to allow checking that the library and the
|
||||||
|
* compiler's view of various types are consistent.
|
||||||
|
*/
|
||||||
|
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
|
||||||
|
(int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
|
||||||
|
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
|
||||||
|
(int)sizeof(lzo_callback_t))
|
||||||
|
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
|
||||||
|
|
||||||
|
/* version functions (useful for shared libraries) */
|
||||||
|
LZO_EXTERN(unsigned) lzo_version(void);
|
||||||
|
LZO_EXTERN(const char *) lzo_version_string(void);
|
||||||
|
LZO_EXTERN(const char *) lzo_version_date(void);
|
||||||
|
LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
|
||||||
|
LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
|
||||||
|
|
||||||
|
/* string functions */
|
||||||
|
LZO_EXTERN(int)
|
||||||
|
lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
|
||||||
|
LZO_EXTERN(lzo_voidp)
|
||||||
|
lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||||
|
LZO_EXTERN(lzo_voidp)
|
||||||
|
lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
|
||||||
|
LZO_EXTERN(lzo_voidp)
|
||||||
|
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
|
||||||
|
|
||||||
|
/* checksum functions */
|
||||||
|
LZO_EXTERN(lzo_uint32)
|
||||||
|
lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||||
|
LZO_EXTERN(lzo_uint32)
|
||||||
|
lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
|
||||||
|
LZO_EXTERN(const lzo_uint32p)
|
||||||
|
lzo_get_crc32_table(void);
|
||||||
|
|
||||||
|
/* misc. */
|
||||||
|
LZO_EXTERN(int) _lzo_config_check(void);
|
||||||
|
typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
|
||||||
|
typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
|
||||||
|
typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t;
|
||||||
|
|
||||||
|
/* align a char pointer on a boundary that is a multiple of 'size' */
|
||||||
|
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
|
||||||
|
#define LZO_PTR_ALIGN_UP(p,size) \
|
||||||
|
((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
// deprecated macros - only for backward compatibility with LZO v1.xx
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#if defined(LZO_CFG_COMPAT)
|
||||||
|
|
||||||
|
#define __LZOCONF_H 1
|
||||||
|
|
||||||
|
#if defined(LZO_ARCH_I086)
|
||||||
|
# define __LZO_i386 1
|
||||||
|
#elif defined(LZO_ARCH_I386)
|
||||||
|
# define __LZO_i386 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(LZO_OS_DOS16)
|
||||||
|
# define __LZO_DOS 1
|
||||||
|
# define __LZO_DOS16 1
|
||||||
|
#elif defined(LZO_OS_DOS32)
|
||||||
|
# define __LZO_DOS 1
|
||||||
|
#elif defined(LZO_OS_WIN16)
|
||||||
|
# define __LZO_WIN 1
|
||||||
|
# define __LZO_WIN16 1
|
||||||
|
#elif defined(LZO_OS_WIN32)
|
||||||
|
# define __LZO_WIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __LZO_CMODEL /*empty*/
|
||||||
|
#define __LZO_DMODEL /*empty*/
|
||||||
|
#define __LZO_ENTRY __LZO_CDECL
|
||||||
|
#define LZO_EXTERN_CDECL LZO_EXTERN
|
||||||
|
#define LZO_ALIGN LZO_PTR_ALIGN_UP
|
||||||
|
|
||||||
|
#define lzo_compress_asm_t lzo_compress_t
|
||||||
|
#define lzo_decompress_asm_t lzo_decompress_t
|
||||||
|
|
||||||
|
#endif /* LZO_CFG_COMPAT */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/* vim:set ts=4 et: */
|
1852
source/goomba/minilzo-2.06/lzodefs.h
Normal file
4579
source/goomba/minilzo-2.06/minilzo.cpp
Normal file
109
source/goomba/minilzo-2.06/minilzo.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* minilzo.h -- mini subset of the LZO real-time data compression library
|
||||||
|
|
||||||
|
This file is part of the LZO real-time data compression library.
|
||||||
|
|
||||||
|
Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
The LZO library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The LZO library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with the LZO library; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
http://www.oberhumer.com/opensource/lzo/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE:
|
||||||
|
* the full LZO package can be found at
|
||||||
|
* http://www.oberhumer.com/opensource/lzo/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MINILZO_H
|
||||||
|
#define __MINILZO_H 1
|
||||||
|
|
||||||
|
#define MINILZO_VERSION 0x2060
|
||||||
|
|
||||||
|
#ifdef __LZOCONF_H
|
||||||
|
# error "you cannot use both LZO and miniLZO"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef LZO_HAVE_CONFIG_H
|
||||||
|
#include "lzoconf.h"
|
||||||
|
|
||||||
|
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
|
||||||
|
# error "version mismatch in header files"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
//
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/* Memory required for the wrkmem parameter.
|
||||||
|
* When the required size is 0, you can also pass a NULL pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
|
||||||
|
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
|
||||||
|
#define LZO1X_MEM_DECOMPRESS (0)
|
||||||
|
|
||||||
|
|
||||||
|
/* compression */
|
||||||
|
LZO_EXTERN(int)
|
||||||
|
lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem );
|
||||||
|
|
||||||
|
/* decompression */
|
||||||
|
LZO_EXTERN(int)
|
||||||
|
lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem /* NOT USED */ );
|
||||||
|
|
||||||
|
/* safe decompression with overrun testing */
|
||||||
|
LZO_EXTERN(int)
|
||||||
|
lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
|
||||||
|
lzo_bytep dst, lzo_uintp dst_len,
|
||||||
|
lzo_voidp wrkmem /* NOT USED */ );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
@ -123,6 +123,16 @@ typedef struct _paddata {
|
|||||||
u8 triggerR;
|
u8 triggerR;
|
||||||
} PADData;
|
} PADData;
|
||||||
|
|
||||||
|
typedef struct _wupcfulldata {
|
||||||
|
u32 btns_d;
|
||||||
|
u32 btns_u;
|
||||||
|
u32 btns_h;
|
||||||
|
s16 stickX;
|
||||||
|
s16 stickY;
|
||||||
|
s16 substickX;
|
||||||
|
s16 substickY;
|
||||||
|
} WUPCFullData;
|
||||||
|
|
||||||
#define EFFECT_SLIDE_TOP 1
|
#define EFFECT_SLIDE_TOP 1
|
||||||
#define EFFECT_SLIDE_BOTTOM 2
|
#define EFFECT_SLIDE_BOTTOM 2
|
||||||
#define EFFECT_SLIDE_RIGHT 4
|
#define EFFECT_SLIDE_RIGHT 4
|
||||||
@ -226,6 +236,7 @@ class GuiTrigger
|
|||||||
|
|
||||||
WPADData wpaddata; //!< Wii controller trigger data
|
WPADData wpaddata; //!< Wii controller trigger data
|
||||||
PADData pad; //!< GameCube controller trigger data
|
PADData pad; //!< GameCube controller trigger data
|
||||||
|
WUPCFullData wupcdata; //!< WiiU Pro controller trigger data
|
||||||
WPADData * wpad; //!< Wii controller trigger
|
WPADData * wpad; //!< Wii controller trigger
|
||||||
s32 chan; //!< Trigger controller channel (0-3, -1 for all)
|
s32 chan; //!< Trigger controller channel (0-3, -1 for all)
|
||||||
u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS)
|
u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS)
|
||||||
@ -240,7 +251,7 @@ class GuiElement
|
|||||||
//!Constructor
|
//!Constructor
|
||||||
GuiElement();
|
GuiElement();
|
||||||
//!Destructor
|
//!Destructor
|
||||||
~GuiElement();
|
virtual ~GuiElement();
|
||||||
//!Set the element's parent
|
//!Set the element's parent
|
||||||
//!\param e Pointer to parent element
|
//!\param e Pointer to parent element
|
||||||
void SetParent(GuiElement * e);
|
void SetParent(GuiElement * e);
|
||||||
|
@ -254,7 +254,7 @@ void GuiButton::Update(GuiTrigger * t)
|
|||||||
// button triggers
|
// button triggers
|
||||||
if(this->IsClickable())
|
if(this->IsClickable())
|
||||||
{
|
{
|
||||||
s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig;
|
s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig, wupc_btns, wupc_btns_trig;
|
||||||
for(int i=0; i<3; i++)
|
for(int i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
|
if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
|
||||||
@ -267,11 +267,16 @@ void GuiButton::Update(GuiTrigger * t)
|
|||||||
cc_btns = t->wpad->btns_d >> 16;
|
cc_btns = t->wpad->btns_d >> 16;
|
||||||
cc_btns_trig = trigger[i]->wpad->btns_d >> 16;
|
cc_btns_trig = trigger[i]->wpad->btns_d >> 16;
|
||||||
|
|
||||||
|
// lower 16 bits only (WiiU Pro controller)
|
||||||
|
wupc_btns = t->wupcdata.btns_d >> 16;
|
||||||
|
wupc_btns_trig = trigger[i]->wupcdata.btns_d >> 16;
|
||||||
|
|
||||||
if(
|
if(
|
||||||
(t->wpad->btns_d > 0 &&
|
(t->wpad->btns_d > 0 &&
|
||||||
(wm_btns == wm_btns_trig ||
|
(wm_btns == wm_btns_trig ||
|
||||||
(cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
(cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
||||||
(t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0))
|
(t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0) ||
|
||||||
|
(wupc_btns == wupc_btns_trig && wupc_btns_trig > 0))
|
||||||
{
|
{
|
||||||
if(t->chan == stateChan || stateChan == -1)
|
if(t->chan == stateChan || stateChan == -1)
|
||||||
{
|
{
|
||||||
@ -303,7 +308,7 @@ void GuiButton::Update(GuiTrigger * t)
|
|||||||
if(this->IsHoldable())
|
if(this->IsHoldable())
|
||||||
{
|
{
|
||||||
bool held = false;
|
bool held = false;
|
||||||
s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig;
|
s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig, wupc_btns, wupc_btns_h, wupc_btns_trig;
|
||||||
|
|
||||||
for(int i=0; i<3; i++)
|
for(int i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
@ -319,11 +324,17 @@ void GuiButton::Update(GuiTrigger * t)
|
|||||||
cc_btns_h = t->wpad->btns_h >> 16;
|
cc_btns_h = t->wpad->btns_h >> 16;
|
||||||
cc_btns_trig = trigger[i]->wpad->btns_h >> 16;
|
cc_btns_trig = trigger[i]->wpad->btns_h >> 16;
|
||||||
|
|
||||||
|
// lower 16 bits only (WiiU Pro controller)
|
||||||
|
wupc_btns = t->wpad->btns_d >> 16;
|
||||||
|
wupc_btns_h = t->wpad->btns_h >> 16;
|
||||||
|
wupc_btns_trig = trigger[i]->wpad->btns_h >> 16;
|
||||||
|
|
||||||
if(
|
if(
|
||||||
(t->wpad->btns_d > 0 &&
|
(t->wpad->btns_d > 0 &&
|
||||||
(wm_btns == wm_btns_trig ||
|
(wm_btns == wm_btns_trig ||
|
||||||
(cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
(cc_btns == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
||||||
(t->pad.btns_d == trigger[i]->pad.btns_h && t->pad.btns_d > 0))
|
(t->pad.btns_d == trigger[i]->pad.btns_h && t->pad.btns_d > 0) ||
|
||||||
|
(wupc_btns == wupc_btns_trig && wupc_btns > 0))
|
||||||
{
|
{
|
||||||
if(trigger[i]->type == TRIGGER_HELD && state == STATE_SELECTED &&
|
if(trigger[i]->type == TRIGGER_HELD && state == STATE_SELECTED &&
|
||||||
(t->chan == stateChan || stateChan == -1))
|
(t->chan == stateChan || stateChan == -1))
|
||||||
@ -334,7 +345,8 @@ void GuiButton::Update(GuiTrigger * t)
|
|||||||
(t->wpad->btns_h > 0 &&
|
(t->wpad->btns_h > 0 &&
|
||||||
(wm_btns_h == wm_btns_trig ||
|
(wm_btns_h == wm_btns_trig ||
|
||||||
(cc_btns_h == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
(cc_btns_h == cc_btns_trig && t->wpad->exp.type == EXP_CLASSIC))) ||
|
||||||
(t->pad.btns_h == trigger[i]->pad.btns_h && t->pad.btns_h > 0))
|
(t->pad.btns_h == trigger[i]->pad.btns_h && t->pad.btns_h > 0) ||
|
||||||
|
(wupc_btns_h == wupc_btns_trig && wupc_btns_h > 0))
|
||||||
{
|
{
|
||||||
if(trigger[i]->type == TRIGGER_HELD)
|
if(trigger[i]->type == TRIGGER_HELD)
|
||||||
held = true;
|
held = true;
|
||||||
|
@ -108,12 +108,12 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
|
|||||||
fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff});
|
fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff});
|
||||||
fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
||||||
fileListText[i]->SetPosition(5,0);
|
fileListText[i]->SetPosition(5,0);
|
||||||
fileListText[i]->SetMaxWidth(380);
|
fileListText[i]->SetMaxWidth(295);
|
||||||
|
|
||||||
fileListBg[i] = new GuiImage(bgFileSelectionEntry);
|
fileListBg[i] = new GuiImage(bgFileSelectionEntry);
|
||||||
fileListIcon[i] = NULL;
|
fileListIcon[i] = NULL;
|
||||||
|
|
||||||
fileList[i] = new GuiButton(380, 26);
|
fileList[i] = new GuiButton(295, 26);
|
||||||
fileList[i]->SetParent(this);
|
fileList[i]->SetParent(this);
|
||||||
fileList[i]->SetLabel(fileListText[i]);
|
fileList[i]->SetLabel(fileListText[i]);
|
||||||
fileList[i]->SetImageOver(fileListBg[i]);
|
fileList[i]->SetImageOver(fileListBg[i]);
|
||||||
|
@ -22,7 +22,8 @@ static char * GetDisplayText(char * t)
|
|||||||
if(len < MAX_KEYBOARD_DISPLAY)
|
if(len < MAX_KEYBOARD_DISPLAY)
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
snprintf(tmptxt, MAX_KEYBOARD_DISPLAY, "%s", &t[len-MAX_KEYBOARD_DISPLAY]);
|
strncpy(tmptxt, &t[len-MAX_KEYBOARD_DISPLAY], MAX_KEYBOARD_DISPLAY);
|
||||||
|
tmptxt[MAX_KEYBOARD_DISPLAY-1] = 0;
|
||||||
return &tmptxt[0];
|
return &tmptxt[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
focus = 0; // allow focus
|
focus = 0; // allow focus
|
||||||
alignmentHor = ALIGN_CENTRE;
|
alignmentHor = ALIGN_CENTRE;
|
||||||
alignmentVert = ALIGN_MIDDLE;
|
alignmentVert = ALIGN_MIDDLE;
|
||||||
snprintf(kbtextstr, 255, "%s", t);
|
strncpy(kbtextstr, t, max);
|
||||||
|
kbtextstr[max] = 0;
|
||||||
kbtextmaxlen = max;
|
kbtextmaxlen = max;
|
||||||
|
|
||||||
Key thekeys[4][11] = {
|
Key thekeys[4][11] = {
|
||||||
@ -106,7 +108,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
keyTextboxImg->SetPosition(0, 0);
|
keyTextboxImg->SetPosition(0, 0);
|
||||||
this->Append(keyTextboxImg);
|
this->Append(keyTextboxImg);
|
||||||
|
|
||||||
kbText = new GuiText(GetDisplayText(kbtextstr), 22, (GXColor){0, 0, 0, 0xff});
|
kbText = new GuiText(GetDisplayText(kbtextstr), 20, (GXColor){0, 0, 0, 0xff});
|
||||||
kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||||
kbText->SetPosition(0, 13);
|
kbText->SetPosition(0, 13);
|
||||||
this->Append(kbText);
|
this->Append(kbText);
|
||||||
@ -128,7 +130,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
|
|
||||||
keyBackImg = new GuiImage(keyMedium);
|
keyBackImg = new GuiImage(keyMedium);
|
||||||
keyBackOverImg = new GuiImage(keyMediumOver);
|
keyBackOverImg = new GuiImage(keyMediumOver);
|
||||||
keyBackText = new GuiText("Back", 22, (GXColor){0, 0, 0, 0xff});
|
keyBackText = new GuiText("Back", 20, (GXColor){0, 0, 0, 0xff});
|
||||||
keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
||||||
keyBack->SetImage(keyBackImg);
|
keyBack->SetImage(keyBackImg);
|
||||||
keyBack->SetImageOver(keyBackOverImg);
|
keyBack->SetImageOver(keyBackOverImg);
|
||||||
@ -143,7 +145,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
|
|
||||||
keyCapsImg = new GuiImage(keyMedium);
|
keyCapsImg = new GuiImage(keyMedium);
|
||||||
keyCapsOverImg = new GuiImage(keyMediumOver);
|
keyCapsOverImg = new GuiImage(keyMediumOver);
|
||||||
keyCapsText = new GuiText("Caps", 22, (GXColor){0, 0, 0, 0xff});
|
keyCapsText = new GuiText("Caps", 20, (GXColor){0, 0, 0, 0xff});
|
||||||
keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
||||||
keyCaps->SetImage(keyCapsImg);
|
keyCaps->SetImage(keyCapsImg);
|
||||||
keyCaps->SetImageOver(keyCapsOverImg);
|
keyCaps->SetImageOver(keyCapsOverImg);
|
||||||
@ -158,7 +160,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
|
|
||||||
keyShiftImg = new GuiImage(keyMedium);
|
keyShiftImg = new GuiImage(keyMedium);
|
||||||
keyShiftOverImg = new GuiImage(keyMediumOver);
|
keyShiftOverImg = new GuiImage(keyMediumOver);
|
||||||
keyShiftText = new GuiText("Shift", 22, (GXColor){0, 0, 0, 0xff});
|
keyShiftText = new GuiText("Shift", 20, (GXColor){0, 0, 0, 0xff});
|
||||||
keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
|
||||||
keyShift->SetImage(keyShiftImg);
|
keyShift->SetImage(keyShiftImg);
|
||||||
keyShift->SetImageOver(keyShiftOverImg);
|
keyShift->SetImageOver(keyShiftOverImg);
|
||||||
@ -196,9 +198,9 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max)
|
|||||||
txt[0] = keys[i][j].ch;
|
txt[0] = keys[i][j].ch;
|
||||||
keyImg[i][j] = new GuiImage(key);
|
keyImg[i][j] = new GuiImage(key);
|
||||||
keyImgOver[i][j] = new GuiImage(keyOver);
|
keyImgOver[i][j] = new GuiImage(keyOver);
|
||||||
keyTxt[i][j] = new GuiText(txt, 22, (GXColor){0, 0, 0, 0xff});
|
keyTxt[i][j] = new GuiText(txt, 20, (GXColor){0, 0, 0, 0xff});
|
||||||
keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
|
keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
|
||||||
keyTxt[i][j]->SetPosition(0, -8);
|
keyTxt[i][j]->SetPosition(0, -10);
|
||||||
keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight());
|
keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight());
|
||||||
keyBtn[i][j]->SetImage(keyImg[i][j]);
|
keyBtn[i][j]->SetImage(keyImg[i][j]);
|
||||||
keyBtn[i][j]->SetImageOver(keyImgOver[i][j]);
|
keyBtn[i][j]->SetImageOver(keyImgOver[i][j]);
|
||||||
|
@ -22,6 +22,7 @@ static u32 delay[4];
|
|||||||
GuiTrigger::GuiTrigger()
|
GuiTrigger::GuiTrigger()
|
||||||
{
|
{
|
||||||
chan = -1;
|
chan = -1;
|
||||||
|
memset(&wupcdata, 0, sizeof(WUPCFullData));
|
||||||
memset(&wpaddata, 0, sizeof(WPADData));
|
memset(&wpaddata, 0, sizeof(WPADData));
|
||||||
memset(&pad, 0, sizeof(PADData));
|
memset(&pad, 0, sizeof(PADData));
|
||||||
wpad = &wpaddata;
|
wpad = &wpaddata;
|
||||||
@ -43,6 +44,7 @@ void GuiTrigger::SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
|
|||||||
{
|
{
|
||||||
type = TRIGGER_SIMPLE;
|
type = TRIGGER_SIMPLE;
|
||||||
chan = ch;
|
chan = ch;
|
||||||
|
wupcdata.btns_d = wiibtns;
|
||||||
wpaddata.btns_d = wiibtns;
|
wpaddata.btns_d = wiibtns;
|
||||||
pad.btns_d = gcbtns;
|
pad.btns_d = gcbtns;
|
||||||
}
|
}
|
||||||
@ -56,6 +58,7 @@ void GuiTrigger::SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
|
|||||||
{
|
{
|
||||||
type = TRIGGER_HELD;
|
type = TRIGGER_HELD;
|
||||||
chan = ch;
|
chan = ch;
|
||||||
|
wupcdata.btns_h = wiibtns;
|
||||||
wpaddata.btns_h = wiibtns;
|
wpaddata.btns_h = wiibtns;
|
||||||
pad.btns_h = gcbtns;
|
pad.btns_h = gcbtns;
|
||||||
}
|
}
|
||||||
@ -68,6 +71,7 @@ void GuiTrigger::SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
|
|||||||
{
|
{
|
||||||
type = TRIGGER_BUTTON_ONLY;
|
type = TRIGGER_BUTTON_ONLY;
|
||||||
chan = ch;
|
chan = ch;
|
||||||
|
wupcdata.btns_d = wiibtns;
|
||||||
wpaddata.btns_d = wiibtns;
|
wpaddata.btns_d = wiibtns;
|
||||||
pad.btns_d = gcbtns;
|
pad.btns_d = gcbtns;
|
||||||
}
|
}
|
||||||
@ -81,6 +85,7 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
|
|||||||
{
|
{
|
||||||
type = TRIGGER_BUTTON_ONLY_IN_FOCUS;
|
type = TRIGGER_BUTTON_ONLY_IN_FOCUS;
|
||||||
chan = ch;
|
chan = ch;
|
||||||
|
wupcdata.btns_d = wiibtns;
|
||||||
wpaddata.btns_d = wiibtns;
|
wpaddata.btns_d = wiibtns;
|
||||||
pad.btns_d = gcbtns;
|
pad.btns_d = gcbtns;
|
||||||
}
|
}
|
||||||
@ -158,11 +163,14 @@ bool GuiTrigger::Left()
|
|||||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT;
|
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT;
|
||||||
|
|
||||||
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|
||||||
|
|| (wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|
||||||
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT
|
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT
|
||||||
|| pad.stickX < -PADCAL
|
|| pad.stickX < -PADCAL
|
||||||
|| WPAD_StickX(0) < -PADCAL)
|
|| WPAD_StickX(0) < -PADCAL
|
||||||
|
|| wupcdata.stickX < -WUPCCAL)
|
||||||
{
|
{
|
||||||
if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|
if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT))
|
||||||
|
|| (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT))
|
||||||
|| pad.btns_d & PAD_BUTTON_LEFT)
|
|| pad.btns_d & PAD_BUTTON_LEFT)
|
||||||
{
|
{
|
||||||
prev[chan] = gettime();
|
prev[chan] = gettime();
|
||||||
@ -191,11 +199,14 @@ bool GuiTrigger::Right()
|
|||||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT;
|
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT;
|
||||||
|
|
||||||
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)
|
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)
|
||||||
|
|| ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT))
|
||||||
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT
|
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT
|
||||||
|| pad.stickX > PADCAL
|
|| pad.stickX > PADCAL
|
||||||
|| WPAD_StickX(0) > PADCAL)
|
|| WPAD_StickX(0) > PADCAL
|
||||||
|
|| wupcdata.stickX > WUPCCAL)
|
||||||
{
|
{
|
||||||
if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)
|
if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT))
|
||||||
|
|| (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT))
|
||||||
|| pad.btns_d & PAD_BUTTON_RIGHT)
|
|| pad.btns_d & PAD_BUTTON_RIGHT)
|
||||||
{
|
{
|
||||||
prev[chan] = gettime();
|
prev[chan] = gettime();
|
||||||
@ -223,12 +234,15 @@ bool GuiTrigger::Up()
|
|||||||
{
|
{
|
||||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP;
|
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP;
|
||||||
|
|
||||||
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP)
|
if(((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP))
|
||||||
|
|| ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP))
|
||||||
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP
|
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP
|
||||||
|| pad.stickY > PADCAL
|
|| pad.stickY > PADCAL
|
||||||
|| WPAD_StickY(0) > PADCAL)
|
|| WPAD_StickY(0) > PADCAL
|
||||||
|
|| wupcdata.stickY > WUPCCAL)
|
||||||
{
|
{
|
||||||
if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP)
|
if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP))
|
||||||
|
|| (wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_UP))
|
||||||
|| pad.btns_d & PAD_BUTTON_UP)
|
|| pad.btns_d & PAD_BUTTON_UP)
|
||||||
{
|
{
|
||||||
prev[chan] = gettime();
|
prev[chan] = gettime();
|
||||||
@ -256,12 +270,15 @@ bool GuiTrigger::Down()
|
|||||||
{
|
{
|
||||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_LEFT : WPAD_BUTTON_DOWN;
|
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_LEFT : WPAD_BUTTON_DOWN;
|
||||||
|
|
||||||
if((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)
|
if(((wpad->btns_d | wpad->btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN))
|
||||||
|
|| ((wupcdata.btns_d | wupcdata.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN))
|
||||||
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_DOWN
|
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_DOWN
|
||||||
|| pad.stickY < -PADCAL
|
|| pad.stickY < -PADCAL
|
||||||
|| WPAD_StickY(0) < -PADCAL)
|
|| WPAD_StickY(0) < -PADCAL
|
||||||
|
|| wupcdata.stickY < -WUPCCAL)
|
||||||
{
|
{
|
||||||
if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)
|
if((wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN))
|
||||||
|
|| wupcdata.btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_DOWN)
|
||||||
|| pad.btns_d & PAD_BUTTON_DOWN)
|
|| pad.btns_d & PAD_BUTTON_DOWN)
|
||||||
{
|
{
|
||||||
prev[chan] = gettime();
|
prev[chan] = gettime();
|
||||||
|
@ -228,8 +228,8 @@ void GuiWindow::ToggleFocus(GuiTrigger * t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// change focus
|
// change focus
|
||||||
else if(t->wpad->btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)
|
else if((t->wpad->btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B))
|
||||||
|| t->pad.btns_d & PAD_BUTTON_B)
|
|| (t->pad.btns_d & PAD_BUTTON_B) || (t->wupcdata.btns_d & WPAD_CLASSIC_BUTTON_B))
|
||||||
{
|
{
|
||||||
for (i = found; i < elemSize; ++i)
|
for (i = found; i < elemSize; ++i)
|
||||||
{
|
{
|
||||||
|
BIN
source/images/bg_preview.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 69 KiB |
BIN
source/images/icon_settings_screenshot.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
source/images/icon_settings_wiiupro.png
Normal file
After Width: | Height: | Size: 10 KiB |
@ -16,6 +16,7 @@
|
|||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wiiuse/wpad.h>
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <wupc/wupc.h>
|
||||||
#include <ogc/lwp_watchdog.h>
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
|
||||||
#include "vbagx.h"
|
#include "vbagx.h"
|
||||||
@ -138,6 +139,7 @@ void
|
|||||||
UpdatePads()
|
UpdatePads()
|
||||||
{
|
{
|
||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
|
WUPC_UpdateButtonStats();
|
||||||
WPAD_ScanPads();
|
WPAD_ScanPads();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -154,6 +156,15 @@ UpdatePads()
|
|||||||
userInput[i].pad.substickY = PAD_SubStickY(i);
|
userInput[i].pad.substickY = PAD_SubStickY(i);
|
||||||
userInput[i].pad.triggerL = PAD_TriggerL(i);
|
userInput[i].pad.triggerL = PAD_TriggerL(i);
|
||||||
userInput[i].pad.triggerR = PAD_TriggerR(i);
|
userInput[i].pad.triggerR = PAD_TriggerR(i);
|
||||||
|
#ifdef HW_RVL
|
||||||
|
userInput[i].wupcdata.btns_d = WUPC_ButtonsDown(i);
|
||||||
|
userInput[i].wupcdata.btns_u = WUPC_ButtonsUp(i);
|
||||||
|
userInput[i].wupcdata.btns_h = WUPC_ButtonsHeld(i);
|
||||||
|
userInput[i].wupcdata.stickX = WUPC_lStickX(i);
|
||||||
|
userInput[i].wupcdata.stickY = WUPC_lStickY(i);
|
||||||
|
userInput[i].wupcdata.substickX = WUPC_rStickX(i);
|
||||||
|
userInput[i].wupcdata.substickY = WUPC_rStickY(i);
|
||||||
|
#endif
|
||||||
--i;
|
--i;
|
||||||
} while(i >= 0);
|
} while(i >= 0);
|
||||||
}
|
}
|
||||||
@ -311,6 +322,9 @@ u32 StandardMovement(unsigned short chan)
|
|||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
s8 wm_ax = userInput[0].WPAD_StickX(0);
|
s8 wm_ax = userInput[0].WPAD_StickX(0);
|
||||||
s8 wm_ay = userInput[0].WPAD_StickY(0);
|
s8 wm_ay = userInput[0].WPAD_StickY(0);
|
||||||
|
|
||||||
|
s16 wupc_ax = userInput[chan].wupcdata.stickX;
|
||||||
|
s16 wupc_ay = userInput[chan].wupcdata.stickY;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -338,7 +352,19 @@ u32 StandardMovement(unsigned short chan)
|
|||||||
if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL)
|
if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL)
|
||||||
{
|
{
|
||||||
angle = atan2(wm_ay, wm_ax);
|
angle = atan2(wm_ay, wm_ax);
|
||||||
|
if(cos(angle) > THRES)
|
||||||
|
J |= VBA_RIGHT;
|
||||||
|
else if(cos(angle) < -THRES)
|
||||||
|
J |= VBA_LEFT;
|
||||||
|
if(sin(angle) > THRES)
|
||||||
|
J |= VBA_UP;
|
||||||
|
else if(sin(angle) < -THRES)
|
||||||
|
J |= VBA_DOWN;
|
||||||
|
}
|
||||||
|
/* WiiU Pro Controller */
|
||||||
|
if (wupc_ax * wupc_ax + wupc_ay * wupc_ay > WUPCCAL * WUPCCAL)
|
||||||
|
{
|
||||||
|
angle = atan2(wupc_ay, wupc_ax);
|
||||||
if(cos(angle) > THRES)
|
if(cos(angle) > THRES)
|
||||||
J |= VBA_RIGHT;
|
J |= VBA_RIGHT;
|
||||||
else if(cos(angle) < -THRES)
|
else if(cos(angle) < -THRES)
|
||||||
@ -380,7 +406,19 @@ u32 StandardDPad(unsigned short pad)
|
|||||||
if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
|
if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
|
||||||
J |= VBA_RIGHT;
|
J |= VBA_RIGHT;
|
||||||
}
|
}
|
||||||
|
/* WiiU Pro Controller */
|
||||||
|
u32 wupcp = userInput[pad].wupcdata.btns_h;
|
||||||
|
if (wupcp & WPAD_CLASSIC_BUTTON_UP)
|
||||||
|
J |= VBA_UP;
|
||||||
|
if (wupcp & WPAD_CLASSIC_BUTTON_DOWN)
|
||||||
|
J |= VBA_DOWN;
|
||||||
|
if (wupcp & WPAD_CLASSIC_BUTTON_LEFT)
|
||||||
|
J |= VBA_LEFT;
|
||||||
|
if (wupcp & WPAD_CLASSIC_BUTTON_RIGHT)
|
||||||
|
J |= VBA_RIGHT;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (jp & PAD_BUTTON_UP)
|
if (jp & PAD_BUTTON_UP)
|
||||||
J |= VBA_UP;
|
J |= VBA_UP;
|
||||||
if (jp & PAD_BUTTON_DOWN)
|
if (jp & PAD_BUTTON_DOWN)
|
||||||
@ -436,7 +474,8 @@ u32 StandardClassic(unsigned short pad)
|
|||||||
{
|
{
|
||||||
u32 J = 0;
|
u32 J = 0;
|
||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
u32 wp = userInput[pad].wpad->btns_h;
|
u32 wp = userInput[pad].wpad->btns_h
|
||||||
|
| userInput[pad].wupcdata.btns_h; /* just add pro controller */
|
||||||
|
|
||||||
if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
|
if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
|
||||||
J |= VBA_RIGHT;
|
J |= VBA_RIGHT;
|
||||||
@ -536,6 +575,14 @@ u32 DecodeClassic(unsigned short pad)
|
|||||||
WPADData * wp = WPAD_Data(pad);
|
WPADData * wp = WPAD_Data(pad);
|
||||||
u32 wpad_btns_h = wp->btns_h;
|
u32 wpad_btns_h = wp->btns_h;
|
||||||
|
|
||||||
|
/* WiiU Pro Controller */
|
||||||
|
u32 wupc_btns_h = userInput[pad].wupcdata.btns_h;
|
||||||
|
for (u32 i = 0; i < MAXJP; ++i)
|
||||||
|
{
|
||||||
|
if(wupc_btns_h & btnmap[CTRLR_CLASSIC][i])
|
||||||
|
J |= vbapadmap[i];
|
||||||
|
}
|
||||||
|
|
||||||
if(wp->exp.type == WPAD_EXP_CLASSIC){
|
if(wp->exp.type == WPAD_EXP_CLASSIC){
|
||||||
for (u32 i = 0; i < MAXJP; ++i){
|
for (u32 i = 0; i < MAXJP; ++i){
|
||||||
if (wpad_btns_h & btnmap[CTRLR_CLASSIC][i] )
|
if (wpad_btns_h & btnmap[CTRLR_CLASSIC][i] )
|
||||||
@ -811,13 +858,16 @@ static u32 DecodeJoy(unsigned short pad)
|
|||||||
case CVHARMONY:
|
case CVHARMONY:
|
||||||
case CVARIA:
|
case CVARIA:
|
||||||
return CastlevaniaCircleMoonInput(pad);
|
return CastlevaniaCircleMoonInput(pad);
|
||||||
|
|
||||||
|
case KIDDRACULA:
|
||||||
|
return KidDraculaInput(pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the function result, J, is a combination of flags for all the VBA buttons that are down
|
// the function result, J, is a combination of flags for all the VBA buttons that are down
|
||||||
u32 J = StandardMovement(pad);
|
u32 J = StandardMovement(pad);
|
||||||
|
|
||||||
// Turbo feature
|
// Turbo feature
|
||||||
if(userInput[0].pad.substickX > 70 || userInput[0].WPAD_Stick(1,0) > 70)
|
if(userInput[0].pad.substickX > 70 || userInput[0].WPAD_Stick(1,0) > 70 || userInput[0].wupcdata.substickX > 560)
|
||||||
J |= VBA_SPEED;
|
J |= VBA_SPEED;
|
||||||
|
|
||||||
// Report pressed buttons (gamepads)
|
// Report pressed buttons (gamepads)
|
||||||
@ -849,6 +899,7 @@ static u32 DecodeJoy(unsigned short pad)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(wpad_exp_type == WPAD_EXP_NUNCHUK)
|
else if(wpad_exp_type == WPAD_EXP_NUNCHUK)
|
||||||
{ // nunchuk + wiimote
|
{ // nunchuk + wiimote
|
||||||
|
|
||||||
@ -858,8 +909,8 @@ static u32 DecodeJoy(unsigned short pad)
|
|||||||
|| ( (wpad_btns_h & btnmap[CTRLR_NUNCHUK][i]) ))
|
|| ( (wpad_btns_h & btnmap[CTRLR_NUNCHUK][i]) ))
|
||||||
J |= vbapadmap[i];
|
J |= vbapadmap[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
// Check out this trickery!
|
// Check out this trickery!
|
||||||
// If all else fails OR if HW_RVL is undefined, the result is the same
|
// If all else fails OR if HW_RVL is undefined, the result is the same
|
||||||
@ -871,32 +922,38 @@ static u32 DecodeJoy(unsigned short pad)
|
|||||||
J |= vbapadmap[i];
|
J |= vbapadmap[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
/* WiiU Pro Controller */
|
||||||
|
u32 wupc_btns_h = userInput[pad].wupcdata.btns_h;
|
||||||
|
for (u32 i =0; i < MAXJP; ++i)
|
||||||
|
{
|
||||||
|
if(wupc_btns_h & btnmap[CTRLR_CLASSIC][i])
|
||||||
|
J |= vbapadmap[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return J;
|
return J;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuRequested()
|
bool MenuRequested()
|
||||||
{
|
{
|
||||||
if( (userInput[0].pad.substickX < -70) ||
|
for(int i=0; i<4; i++)
|
||||||
(userInput[0].wpad->btns_h & WPAD_BUTTON_HOME) ||
|
{
|
||||||
(userInput[0].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
|
if (
|
||||||
||
|
(userInput[i].pad.substickX < -70)
|
||||||
(userInput[1].pad.substickX < -70) ||
|
#ifdef HW_RVL
|
||||||
(userInput[1].wpad->btns_h & WPAD_BUTTON_HOME) ||
|
|| (userInput[i].wpad->btns_h & WPAD_BUTTON_HOME) ||
|
||||||
(userInput[1].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
|
(userInput[i].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME) ||
|
||||||
||
|
(userInput[i].wupcdata.btns_h & WPAD_CLASSIC_BUTTON_HOME)
|
||||||
(userInput[2].pad.substickX < -70) ||
|
#endif
|
||||||
(userInput[2].wpad->btns_h & WPAD_BUTTON_HOME) ||
|
|
||||||
(userInput[2].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
|
|
||||||
||
|
|
||||||
(userInput[3].pad.substickX < -70) ||
|
|
||||||
(userInput[3].wpad->btns_h & WPAD_BUTTON_HOME) ||
|
|
||||||
(userInput[3].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetJoy(int pad)
|
u32 GetJoy(int pad)
|
||||||
{
|
{
|
||||||
@ -915,5 +972,6 @@ u32 GetJoy(int pad)
|
|||||||
if ((J & 192) == 192)
|
if ((J & 192) == 192)
|
||||||
J &= ~128;
|
J &= ~128;
|
||||||
updateRumbleFrame();
|
updateRumbleFrame();
|
||||||
|
|
||||||
return J;
|
return J;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#define PI 3.14159265f
|
#define PI 3.14159265f
|
||||||
#define PADCAL 50
|
#define PADCAL 50
|
||||||
|
#define WUPCCAL 400
|
||||||
#define MAXJP 10 // # of mappable controller buttons
|
#define MAXJP 10 // # of mappable controller buttons
|
||||||
|
|
||||||
#define VBA_BUTTON_A 1
|
#define VBA_BUTTON_A 1
|
||||||
|
@ -396,13 +396,8 @@ u32 MarioLand2Input(unsigned short pad) {
|
|||||||
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
|
if (wp->btns_h & WPAD_CLASSIC_BUTTON_X || wp->btns_h & WPAD_CLASSIC_BUTTON_Y || run)
|
||||||
J |= VBA_BUTTON_B;
|
J |= VBA_BUTTON_B;
|
||||||
// Spin attack
|
// Spin attack
|
||||||
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A)
|
if (wp->btns_h & WPAD_CLASSIC_BUTTON_A || wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
|
||||||
J |= VBA_DOWN | VBA_BUTTON_A;
|
J |= VBA_DOWN | VBA_BUTTON_A;
|
||||||
// Camera
|
|
||||||
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_L)
|
|
||||||
J |= VBA_DOWN | VBA_BUTTON_B;
|
|
||||||
if (wp->btns_h & WPAD_CLASSIC_BUTTON_FULL_R)
|
|
||||||
J |= VBA_UP | VBA_BUTTON_B;
|
|
||||||
// Crouch
|
// Crouch
|
||||||
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL && (!(wp->btns_h & WPAD_CLASSIC_BUTTON_A))) {
|
if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL && (!(wp->btns_h & WPAD_CLASSIC_BUTTON_A))) {
|
||||||
J |= VBA_DOWN;
|
J |= VBA_DOWN;
|
||||||
|
@ -241,6 +241,18 @@ msgstr "Presione un bot
|
|||||||
msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping."
|
msgid "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping."
|
||||||
msgstr "Presione un botón en el Wiimote o Nunchuck. Presione HOME para eliminar la configuración actual."
|
msgstr "Presione un botón en el Wiimote o Nunchuck. Presione HOME para eliminar la configuración actual."
|
||||||
|
|
||||||
|
msgid "Press any button on the Wii U Pro Controller now. Press Home to clear the existing mapping."
|
||||||
|
msgstr "Presione un botón en el Mando Wii U Pro. Presione HOME para eliminar la configuración actual."
|
||||||
|
|
||||||
|
msgid "ScreenShot"
|
||||||
|
msgstr "Pantalla"
|
||||||
|
|
||||||
|
msgid "Preview Screenshot"
|
||||||
|
msgstr "Imagen de Pantalla"
|
||||||
|
|
||||||
|
msgid "Save a new Preview Screenshot? Current Screenshot image will be overwritten."
|
||||||
|
msgstr "¿Grabar una nueva imagen de pantalla? La imagen actual será sobre-escrita."
|
||||||
|
|
||||||
msgid "Progressive (480p)"
|
msgid "Progressive (480p)"
|
||||||
msgstr "Progresivo (480p)"
|
msgstr "Progresivo (480p)"
|
||||||
|
|
||||||
|
611
source/menu.cpp
@ -21,6 +21,7 @@ void MainMenu (int menuitem);
|
|||||||
void ErrorPrompt(const char * msg);
|
void ErrorPrompt(const char * msg);
|
||||||
int ErrorPromptRetry(const char * msg);
|
int ErrorPromptRetry(const char * msg);
|
||||||
void InfoPrompt(const char * msg);
|
void InfoPrompt(const char * msg);
|
||||||
|
int YesNoPrompt(const char *msg, bool yesDefault);
|
||||||
void ShowAction (const char *msg);
|
void ShowAction (const char *msg);
|
||||||
void CancelAction();
|
void CancelAction();
|
||||||
void ShowProgress (const char *msg, int done, int total);
|
void ShowProgress (const char *msg, int done, int total);
|
||||||
@ -43,7 +44,8 @@ enum
|
|||||||
MENU_GAMESETTINGS_MAPPINGS_MAP,
|
MENU_GAMESETTINGS_MAPPINGS_MAP,
|
||||||
MENU_GAMESETTINGS_VIDEO,
|
MENU_GAMESETTINGS_VIDEO,
|
||||||
MENU_GAMESETTINGS_CHEATS,
|
MENU_GAMESETTINGS_CHEATS,
|
||||||
MENU_GAMESETTINGS_PALETTE
|
MENU_GAMESETTINGS_PALETTE,
|
||||||
|
MENU_SETTINGS_EMULATION
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* PNGU
|
* PNGU
|
||||||
*
|
*
|
||||||
* Original author: frontier (http://frontier-dev.net)
|
* Original author: frontier (http://frontier-dev.net)
|
||||||
* Modified by Tantric, 2009-2010
|
* This is Tantric's modified/condensed version + RGB565 decoder from original
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -16,18 +16,6 @@
|
|||||||
#define PNGU_SOURCE_BUFFER 1
|
#define PNGU_SOURCE_BUFFER 1
|
||||||
#define PNGU_SOURCE_DEVICE 2
|
#define PNGU_SOURCE_DEVICE 2
|
||||||
|
|
||||||
// Return codes
|
|
||||||
#define PNGU_OK 0
|
|
||||||
#define PNGU_ODD_WIDTH 1
|
|
||||||
#define PNGU_ODD_STRIDE 2
|
|
||||||
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
|
|
||||||
#define PNGU_FILE_IS_NOT_PNG 4
|
|
||||||
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
|
|
||||||
#define PNGU_NO_FILE_SELECTED 6
|
|
||||||
#define PNGU_CANT_OPEN_FILE 7
|
|
||||||
#define PNGU_CANT_READ_FILE 8
|
|
||||||
#define PNGU_LIB_ERROR 9
|
|
||||||
|
|
||||||
// Color types
|
// Color types
|
||||||
#define PNGU_COLOR_TYPE_GRAY 1
|
#define PNGU_COLOR_TYPE_GRAY 1
|
||||||
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
|
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
|
||||||
@ -311,7 +299,7 @@ static int pngu_decode (IMGCTX ctx, u32 width, u32 height, u32 stripAlpha)
|
|||||||
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
||||||
|
|
||||||
// Check if color type is supported by PNGU
|
// Check if color type is supported by PNGU
|
||||||
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) )
|
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN)
|
||||||
return PNGU_UNSUPPORTED_COLOR_TYPE;
|
return PNGU_UNSUPPORTED_COLOR_TYPE;
|
||||||
|
|
||||||
// Scale 16 bit samples to 8 bit
|
// Scale 16 bit samples to 8 bit
|
||||||
@ -330,6 +318,10 @@ static int pngu_decode (IMGCTX ctx, u32 width, u32 height, u32 stripAlpha)
|
|||||||
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) )
|
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) )
|
||||||
png_set_gray_to_rgb (ctx->png_ptr);
|
png_set_gray_to_rgb (ctx->png_ptr);
|
||||||
|
|
||||||
|
// Transform palette images to RGB
|
||||||
|
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_palette_to_rgb(ctx->png_ptr);
|
||||||
|
|
||||||
// Flush transformations
|
// Flush transformations
|
||||||
png_read_update_info (ctx->png_ptr, ctx->info_ptr);
|
png_read_update_info (ctx->png_ptr, ctx->info_ptr);
|
||||||
|
|
||||||
@ -479,6 +471,70 @@ static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, u32 width, u32 height, int * dstW
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, u32 width, u32 height, void *buffer)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
u32 x, y, qwidth, qheight;
|
||||||
|
|
||||||
|
// width and height need to be divisible by four
|
||||||
|
if ((width % 4) || (height % 4))
|
||||||
|
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
||||||
|
|
||||||
|
result = pngu_decode (ctx, width, height, 1);
|
||||||
|
if (result != PNGU_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Copy image to the output buffer
|
||||||
|
qwidth = width / 4;
|
||||||
|
qheight = height / 4;
|
||||||
|
|
||||||
|
for (y = 0; y < qheight; y++)
|
||||||
|
for (x = 0; x < qwidth; x++)
|
||||||
|
{
|
||||||
|
int blockbase = (y * qwidth + x) * 4;
|
||||||
|
|
||||||
|
u64 field64 = *((u64 *)(ctx->row_pointers[y*4]+x*12));
|
||||||
|
u64 field32 = (u64) *((u32 *)(ctx->row_pointers[y*4]+x*12+8));
|
||||||
|
((u64 *) buffer)[blockbase] =
|
||||||
|
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
||||||
|
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
||||||
|
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
||||||
|
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
||||||
|
|
||||||
|
field64 = *((u64 *)(ctx->row_pointers[y*4+1]+x*12));
|
||||||
|
field32 = (u64) *((u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
|
||||||
|
((u64 *) buffer)[blockbase+1] =
|
||||||
|
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
||||||
|
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
||||||
|
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
||||||
|
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
||||||
|
|
||||||
|
field64 = *((u64 *)(ctx->row_pointers[y*4+2]+x*12));
|
||||||
|
field32 = (u64) *((u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
|
||||||
|
((u64 *) buffer)[blockbase+2] =
|
||||||
|
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
||||||
|
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
||||||
|
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
||||||
|
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
||||||
|
|
||||||
|
field64 = *((u64 *)(ctx->row_pointers[y*4+3]+x*12));
|
||||||
|
field32 = (u64) *((u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
|
||||||
|
((u64 *) buffer)[blockbase+3] =
|
||||||
|
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
||||||
|
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
||||||
|
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
||||||
|
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free resources
|
||||||
|
free (ctx->img_data);
|
||||||
|
free (ctx->row_pointers);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
return PNGU_OK;
|
||||||
|
}
|
||||||
|
|
||||||
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
||||||
{
|
{
|
||||||
IMGCTX ctx = NULL;
|
IMGCTX ctx = NULL;
|
||||||
@ -749,3 +805,38 @@ int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height)
|
|||||||
free(tmpbuffer);
|
free(tmpbuffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Added by libertyernie
|
||||||
|
int PNGU_EncodeFromLinearRGB565 (IMGCTX ctx, u32 width, u32 height, const void* buffer, int rowlength)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
u32 x, y, tmpy1, tmpxy;
|
||||||
|
|
||||||
|
u16 * src = (u16 *)buffer;
|
||||||
|
unsigned char * tmpbuffer = malloc(width*height*3);
|
||||||
|
|
||||||
|
if(!tmpbuffer)
|
||||||
|
return PNGU_LIB_ERROR;
|
||||||
|
|
||||||
|
for(y=0; y < height; y++)
|
||||||
|
{
|
||||||
|
tmpy1 = y * width * 3;
|
||||||
|
|
||||||
|
for(x=0; x < width; x++)
|
||||||
|
{
|
||||||
|
tmpxy = x * 3 + tmpy1;
|
||||||
|
u16 color = *src++;
|
||||||
|
tmpbuffer[tmpxy ] = (color >> 11) << 3; // R
|
||||||
|
tmpbuffer[tmpxy+1] = ((color >> 6) & 31) << 3; // G - discard least significant byte
|
||||||
|
tmpbuffer[tmpxy+2] = (color & 31) << 3; // B
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowlength > width) {
|
||||||
|
src += (rowlength - width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, 0);
|
||||||
|
free(tmpbuffer);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* PNGU
|
* PNGU
|
||||||
*
|
*
|
||||||
* Original author: frontier (http://frontier-dev.net)
|
* Original author: frontier (http://frontier-dev.net)
|
||||||
* Modified by Tantric, 2009-2010
|
* This is Tantric's modified/condensed version + RGB565 decoder from original
|
||||||
*
|
*
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
@ -16,6 +16,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Return codes
|
||||||
|
#define PNGU_OK 0
|
||||||
|
#define PNGU_ODD_WIDTH 1
|
||||||
|
#define PNGU_ODD_STRIDE 2
|
||||||
|
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
|
||||||
|
#define PNGU_FILE_IS_NOT_PNG 4
|
||||||
|
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
|
||||||
|
#define PNGU_NO_FILE_SELECTED 6
|
||||||
|
#define PNGU_CANT_OPEN_FILE 7
|
||||||
|
#define PNGU_CANT_READ_FILE 8
|
||||||
|
#define PNGU_LIB_ERROR 9
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 r;
|
u8 r;
|
||||||
@ -68,6 +80,9 @@ int PNGU_EncodeFromRGB (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 str
|
|||||||
int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride);
|
int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride);
|
||||||
int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height);
|
int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height);
|
||||||
|
|
||||||
|
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, u32 width, u32 height, void *buffer);
|
||||||
|
int PNGU_EncodeFromLinearRGB565 (IMGCTX ctx, u32 width, u32 height, const void* buffer, int rowlength);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef SYSTEM_H
|
#ifndef SYSTEM_H
|
||||||
#define SYSTEM_H
|
#define SYSTEM_H
|
||||||
|
|
||||||
#include "common/Types.h"
|
#include "common/Types.h"
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
class SoundDriver;
|
class SoundDriver;
|
||||||
@ -18,10 +16,17 @@ struct EmulatedSystem {
|
|||||||
bool (*emuReadBattery)(const char *);
|
bool (*emuReadBattery)(const char *);
|
||||||
// write battery file
|
// write battery file
|
||||||
bool (*emuWriteBattery)(const char *);
|
bool (*emuWriteBattery)(const char *);
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
// load state
|
||||||
|
bool (*emuReadState)(const u8*, unsigned);
|
||||||
|
// load state
|
||||||
|
unsigned (*emuWriteState)(u8*, unsigned);
|
||||||
|
#else
|
||||||
// load state
|
// load state
|
||||||
bool (*emuReadState)(const char *);
|
bool (*emuReadState)(const char *);
|
||||||
// save state
|
// save state
|
||||||
bool (*emuWriteState)(const char *);
|
bool (*emuWriteState)(const char *);
|
||||||
|
#endif
|
||||||
// load memory state (rewind)
|
// load memory state (rewind)
|
||||||
bool (*emuReadMemState)(char *, int);
|
bool (*emuReadMemState)(char *, int);
|
||||||
// write memory state (rewind)
|
// write memory state (rewind)
|
||||||
@ -39,20 +44,14 @@ struct EmulatedSystem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern void log(const char *,...);
|
extern void log(const char *,...);
|
||||||
|
|
||||||
extern bool systemPauseOnFrame();
|
extern bool systemPauseOnFrame();
|
||||||
extern void systemGbPrint(u8 *,int,int,int,int);
|
extern void systemGbPrint(u8 *,int,int,int,int,int);
|
||||||
extern void systemScreenCapture(int);
|
extern void systemScreenCapture(int);
|
||||||
extern void systemDrawScreen();
|
extern void systemDrawScreen();
|
||||||
// updates the joystick data
|
// updates the joystick data
|
||||||
extern bool systemReadJoypads();
|
extern bool systemReadJoypads();
|
||||||
// return information about the given joystick, -1 for default joystick
|
// return information about the given joystick, -1 for default joystick
|
||||||
extern u32 systemReadJoypad(int);
|
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 u32 systemGetClock();
|
||||||
extern void systemMessage(int, const char *, ...);
|
extern void systemMessage(int, const char *, ...);
|
||||||
extern void systemSetTitle(const char *);
|
extern void systemSetTitle(const char *);
|
||||||
@ -68,19 +67,19 @@ extern void systemShowSpeed(int);
|
|||||||
extern void system10Frames(int);
|
extern void system10Frames(int);
|
||||||
extern void systemFrame();
|
extern void systemFrame();
|
||||||
extern void systemGbBorderOn();
|
extern void systemGbBorderOn();
|
||||||
|
|
||||||
extern void Sm60FPS_Init();
|
extern void Sm60FPS_Init();
|
||||||
extern bool Sm60FPS_CanSkipFrame();
|
extern bool Sm60FPS_CanSkipFrame();
|
||||||
extern void Sm60FPS_Sleep();
|
extern void Sm60FPS_Sleep();
|
||||||
extern void DbgMsg(const char *msg, ...);
|
extern void DbgMsg(const char *msg, ...);
|
||||||
|
#ifdef SDL
|
||||||
|
#define winlog log
|
||||||
|
#else
|
||||||
extern void winlog(const char *,...);
|
extern void winlog(const char *,...);
|
||||||
|
#endif
|
||||||
extern void (*dbgOutput)(const char *s, u32 addr);
|
extern void (*dbgOutput)(const char *s, u32 addr);
|
||||||
extern void (*dbgSignal)(int sig,int number);
|
extern void (*dbgSignal)(int sig,int number);
|
||||||
|
|
||||||
extern u16 systemColorMap16[0x10000];
|
extern u16 systemColorMap16[0x10000];
|
||||||
//extern u32 systemColorMap32[0x10000];
|
extern u32 systemColorMap32[0x10000];
|
||||||
extern u32 *systemColorMap32;
|
|
||||||
extern u16 systemGbPalette[24];
|
extern u16 systemGbPalette[24];
|
||||||
extern int systemRedShift;
|
extern int systemRedShift;
|
||||||
extern int systemGreenShift;
|
extern int systemGreenShift;
|
||||||
@ -91,8 +90,6 @@ extern int systemVerbose;
|
|||||||
extern int systemFrameSkip;
|
extern int systemFrameSkip;
|
||||||
extern int systemSaveUpdateCounter;
|
extern int systemSaveUpdateCounter;
|
||||||
extern int systemSpeed;
|
extern int systemSpeed;
|
||||||
|
|
||||||
#define SYSTEM_SAVE_UPDATED 30
|
#define SYSTEM_SAVE_UPDATED 30
|
||||||
#define SYSTEM_SAVE_NOT_UPDATED 0
|
#define SYSTEM_SAVE_NOT_UPDATED 0
|
||||||
|
|
||||||
#endif // SYSTEM_H
|
#endif // SYSTEM_H
|
||||||
|
@ -1,26 +1,14 @@
|
|||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
|
||||||
// Copyright (C) 2004-2006 Forgotten and the VBA development team
|
|
||||||
// Copyright (C) 2007-2008 VBA-M development team and Shay Green
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#ifndef NO_PNG
|
||||||
|
extern "C" {
|
||||||
|
#include <png.h>
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include "NLS.h"
|
#include "NLS.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
@ -29,12 +17,18 @@
|
|||||||
#include "gba/Globals.h"
|
#include "gba/Globals.h"
|
||||||
#include "gba/RTC.h"
|
#include "gba/RTC.h"
|
||||||
#include "common/Port.h"
|
#include "common/Port.h"
|
||||||
#include "../utils/unzip/unzip.h"
|
|
||||||
|
#ifndef NO_FEX
|
||||||
|
#include "fex/fex.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "common/memgzio.h"
|
#include "common/memgzio.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "gba/gbafilter.h"
|
||||||
|
#include "gb/gbGlobals.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#define _stricmp strcasecmp
|
#define _stricmp strcasecmp
|
||||||
#endif // ! _MSC_VER
|
#endif // ! _MSC_VER
|
||||||
@ -45,13 +39,283 @@ extern int systemGreenShift;
|
|||||||
extern int systemBlueShift;
|
extern int systemBlueShift;
|
||||||
|
|
||||||
extern u16 systemColorMap16[0x10000];
|
extern u16 systemColorMap16[0x10000];
|
||||||
//extern u32 systemColorMap32[0x10000];
|
extern u32 systemColorMap32[0x10000];
|
||||||
extern u32 *systemColorMap32;
|
|
||||||
|
|
||||||
static int (*utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
|
static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
|
||||||
static int (*utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
|
static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
|
||||||
static int (*utilGzCloseFunc)(gzFile) = NULL;
|
static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
|
||||||
static z_off_t (*utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
|
static z_off_t (ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
|
||||||
|
|
||||||
|
bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
|
||||||
|
{
|
||||||
|
#ifndef NO_PNG
|
||||||
|
u8 writeBuffer[512 * 3];
|
||||||
|
|
||||||
|
FILE *fp = fopen(fileName,"wb");
|
||||||
|
|
||||||
|
if(!fp) {
|
||||||
|
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if(!png_ptr) {
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
|
||||||
|
if(!info_ptr) {
|
||||||
|
png_destroy_write_struct(&png_ptr,NULL);
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_write_struct(&png_ptr,NULL);
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_init_io(png_ptr,fp);
|
||||||
|
|
||||||
|
png_set_IHDR(png_ptr,
|
||||||
|
info_ptr,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
8,
|
||||||
|
PNG_COLOR_TYPE_RGB,
|
||||||
|
PNG_INTERLACE_NONE,
|
||||||
|
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||||
|
PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
png_write_info(png_ptr,info_ptr);
|
||||||
|
|
||||||
|
u8 *b = writeBuffer;
|
||||||
|
|
||||||
|
int sizeX = w;
|
||||||
|
int sizeY = h;
|
||||||
|
|
||||||
|
switch(systemColorDepth) {
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
u16 v = *p++;
|
||||||
|
|
||||||
|
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
||||||
|
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
||||||
|
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
|
||||||
|
}
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
png_write_row(png_ptr,writeBuffer);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
{
|
||||||
|
u8 *pixU8 = (u8 *)pix;
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
if(systemRedShift < systemBlueShift) {
|
||||||
|
*b++ = *pixU8++; // R
|
||||||
|
*b++ = *pixU8++; // G
|
||||||
|
*b++ = *pixU8++; // B
|
||||||
|
} else {
|
||||||
|
int blue = *pixU8++;
|
||||||
|
int green = *pixU8++;
|
||||||
|
int red = *pixU8++;
|
||||||
|
|
||||||
|
*b++ = red;
|
||||||
|
*b++ = green;
|
||||||
|
*b++ = blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
png_write_row(png_ptr,writeBuffer);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
{
|
||||||
|
u32 *pixU32 = (u32 *)(pix+4*(w+1));
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
u32 v = *pixU32++;
|
||||||
|
|
||||||
|
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
||||||
|
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
||||||
|
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
||||||
|
}
|
||||||
|
pixU32++;
|
||||||
|
|
||||||
|
png_write_row(png_ptr,writeBuffer);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_write_end(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void utilPutDword(u8 *p, u32 value)
|
||||||
|
{
|
||||||
|
*p++ = value & 255;
|
||||||
|
*p++ = (value >> 8) & 255;
|
||||||
|
*p++ = (value >> 16) & 255;
|
||||||
|
*p = (value >> 24) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
void utilPutWord(u8 *p, u16 value)
|
||||||
|
{
|
||||||
|
*p++ = value & 255;
|
||||||
|
*p = (value >> 8) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
|
||||||
|
{
|
||||||
|
u8 writeBuffer[512 * 3];
|
||||||
|
|
||||||
|
FILE *fp = fopen(fileName,"wb");
|
||||||
|
|
||||||
|
if(!fp) {
|
||||||
|
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 ident[2];
|
||||||
|
u8 filesize[4];
|
||||||
|
u8 reserved[4];
|
||||||
|
u8 dataoffset[4];
|
||||||
|
u8 headersize[4];
|
||||||
|
u8 width[4];
|
||||||
|
u8 height[4];
|
||||||
|
u8 planes[2];
|
||||||
|
u8 bitsperpixel[2];
|
||||||
|
u8 compression[4];
|
||||||
|
u8 datasize[4];
|
||||||
|
u8 hres[4];
|
||||||
|
u8 vres[4];
|
||||||
|
u8 colors[4];
|
||||||
|
u8 importantcolors[4];
|
||||||
|
// u8 pad[2];
|
||||||
|
} bmpheader;
|
||||||
|
memset(&bmpheader, 0, sizeof(bmpheader));
|
||||||
|
|
||||||
|
bmpheader.ident[0] = 'B';
|
||||||
|
bmpheader.ident[1] = 'M';
|
||||||
|
|
||||||
|
u32 fsz = sizeof(bmpheader) + w*h*3;
|
||||||
|
utilPutDword(bmpheader.filesize, fsz);
|
||||||
|
utilPutDword(bmpheader.dataoffset, 0x36);
|
||||||
|
utilPutDword(bmpheader.headersize, 0x28);
|
||||||
|
utilPutDword(bmpheader.width, w);
|
||||||
|
utilPutDword(bmpheader.height, h);
|
||||||
|
utilPutDword(bmpheader.planes, 1);
|
||||||
|
utilPutDword(bmpheader.bitsperpixel, 24);
|
||||||
|
utilPutDword(bmpheader.datasize, 3*w*h);
|
||||||
|
|
||||||
|
fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
|
||||||
|
|
||||||
|
u8 *b = writeBuffer;
|
||||||
|
|
||||||
|
int sizeX = w;
|
||||||
|
int sizeY = h;
|
||||||
|
|
||||||
|
switch(systemColorDepth) {
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
u16 v = *p++;
|
||||||
|
|
||||||
|
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
|
||||||
|
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
||||||
|
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
||||||
|
}
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
p -= 2*(w+2);
|
||||||
|
fwrite(writeBuffer, 1, 3*w, fp);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
{
|
||||||
|
u8 *pixU8 = (u8 *)pix+3*w*(h-1);
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
if(systemRedShift > systemBlueShift) {
|
||||||
|
*b++ = *pixU8++; // B
|
||||||
|
*b++ = *pixU8++; // G
|
||||||
|
*b++ = *pixU8++; // R
|
||||||
|
} else {
|
||||||
|
int red = *pixU8++;
|
||||||
|
int green = *pixU8++;
|
||||||
|
int blue = *pixU8++;
|
||||||
|
|
||||||
|
*b++ = blue;
|
||||||
|
*b++ = green;
|
||||||
|
*b++ = red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pixU8 -= 2*3*w;
|
||||||
|
fwrite(writeBuffer, 1, 3*w, fp);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
{
|
||||||
|
u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
|
||||||
|
for(int y = 0; y < sizeY; y++) {
|
||||||
|
for(int x = 0; x < sizeX; x++) {
|
||||||
|
u32 v = *pixU32++;
|
||||||
|
|
||||||
|
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
||||||
|
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
||||||
|
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
|
||||||
|
}
|
||||||
|
pixU32++;
|
||||||
|
pixU32 -= 2*(w+1);
|
||||||
|
|
||||||
|
fwrite(writeBuffer, 1, 3*w, fp);
|
||||||
|
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern bool cpuIsMultiBoot;
|
extern bool cpuIsMultiBoot;
|
||||||
|
|
||||||
@ -95,15 +359,15 @@ bool utilIsGBImage(const char * file)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool utilIsZipFile(const char *file)
|
bool utilIsGzipFile(const char *file)
|
||||||
{
|
{
|
||||||
if(strlen(file) > 4)
|
if(strlen(file) > 3) {
|
||||||
{
|
const char * p = strrchr(file,'.');
|
||||||
char * p = strrchr(file,'.');
|
|
||||||
|
|
||||||
if(p != NULL)
|
if(p != NULL) {
|
||||||
{
|
if(_stricmp(p, ".gz") == 0)
|
||||||
if(_stricmp(p, ".zip") == 0)
|
return true;
|
||||||
|
if(_stricmp(p, ".z") == 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,18 +375,205 @@ bool utilIsZipFile(const char *file)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void utilPutDword(u8 *p, u32 value)
|
// strip .gz or .z off end
|
||||||
|
void utilStripDoubleExtension(const char *file, char *buffer)
|
||||||
{
|
{
|
||||||
*p++ = value & 255;
|
if(buffer != file) // allows conversion in place
|
||||||
*p++ = (value >> 8) & 255;
|
strcpy(buffer, file);
|
||||||
*p++ = (value >> 16) & 255;
|
|
||||||
*p = (value >> 24) & 255;
|
if(utilIsGzipFile(file)) {
|
||||||
|
char *p = strrchr(buffer, '.');
|
||||||
|
|
||||||
|
if(p)
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void utilPutWord(u8 *p, u16 value)
|
#ifndef NO_FEX
|
||||||
|
// Opens and scans archive using accept(). Returns fex_t if found.
|
||||||
|
// If error or not found, displays message and returns NULL.
|
||||||
|
static fex_t* scan_arc(const char *file, bool (*accept)(const char *),
|
||||||
|
char (&buffer) [2048] )
|
||||||
{
|
{
|
||||||
*p++ = value & 255;
|
fex_t* fe;
|
||||||
*p = (value >> 8) & 255;
|
fex_err_t err = fex_open( &fe, file );
|
||||||
|
if(!fe)
|
||||||
|
{
|
||||||
|
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s: %s"), file, err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan filenames
|
||||||
|
bool found=false;
|
||||||
|
while(!fex_done(fe)) {
|
||||||
|
strncpy(buffer,fex_name(fe),sizeof buffer);
|
||||||
|
buffer [sizeof buffer-1] = '\0';
|
||||||
|
|
||||||
|
utilStripDoubleExtension(buffer, buffer);
|
||||||
|
|
||||||
|
if(accept(buffer)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fex_err_t err = fex_next(fe);
|
||||||
|
if(err) {
|
||||||
|
systemMessage(MSG_BAD_ZIP_FILE, N_("Cannot read archive %s: %s"), file, err);
|
||||||
|
fex_close(fe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
systemMessage(MSG_NO_IMAGE_ON_ZIP,
|
||||||
|
N_("No image found in file %s"), file);
|
||||||
|
fex_close(fe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return fe;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool utilIsImage(const char *file)
|
||||||
|
{
|
||||||
|
return utilIsGBAImage(file) || utilIsGBImage(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
|
||||||
|
|
||||||
|
IMAGE_TYPE utilFindType(const char *file)
|
||||||
|
{
|
||||||
|
char buffer [2048];
|
||||||
|
return utilFindType(file, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
|
||||||
|
{
|
||||||
|
#ifndef NO_FEX
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, file, -1, NULL, 0);
|
||||||
|
wchar_t *pwText;
|
||||||
|
pwText = new wchar_t[dwNum];
|
||||||
|
if(!pwText)
|
||||||
|
{
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
}
|
||||||
|
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
|
||||||
|
char* file_conv = fex_wide_to_path( pwText);
|
||||||
|
// if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead?
|
||||||
|
// {
|
||||||
|
fex_t* fe = scan_arc(file_conv,utilIsImage,buffer);
|
||||||
|
if(!fe)
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
fex_close(fe);
|
||||||
|
file = buffer;
|
||||||
|
// }
|
||||||
|
free(file_conv);
|
||||||
|
#else
|
||||||
|
// if ( !utilIsImage( file ) ) // TODO: utilIsArchive() instead?
|
||||||
|
// {
|
||||||
|
fex_t* fe = scan_arc(file,utilIsImage,buffer);
|
||||||
|
if(!fe)
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
fex_close(fe);
|
||||||
|
file = buffer;
|
||||||
|
// }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int utilGetSize(int size)
|
||||||
|
{
|
||||||
|
int res = 1;
|
||||||
|
while(res < size)
|
||||||
|
res <<= 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *utilLoad(const char *file,
|
||||||
|
bool (*accept)(const char *),
|
||||||
|
u8 *data,
|
||||||
|
int &size)
|
||||||
|
{
|
||||||
|
// find image file
|
||||||
|
char buffer [2048];
|
||||||
|
#ifdef NO_FEX
|
||||||
|
FILE* f = fopen(file, "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
int fileSize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
#else
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, file, -1, NULL, 0);
|
||||||
|
wchar_t *pwText;
|
||||||
|
pwText = new wchar_t[dwNum];
|
||||||
|
if(!pwText)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
|
||||||
|
char* file_conv = fex_wide_to_path( pwText);
|
||||||
|
delete []pwText;
|
||||||
|
fex_t *fe = scan_arc(file_conv,accept,buffer);
|
||||||
|
if(!fe)
|
||||||
|
return NULL;
|
||||||
|
free(file_conv);
|
||||||
|
#else
|
||||||
|
fex_t *fe = scan_arc(file,accept,buffer);
|
||||||
|
if(!fe)
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
// Allocate space for image
|
||||||
|
fex_err_t err = fex_stat(fe);
|
||||||
|
int fileSize = fex_size(fe);
|
||||||
|
if(size == 0)
|
||||||
|
size = fileSize;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u8 *image = data;
|
||||||
|
|
||||||
|
if(image == NULL) {
|
||||||
|
// allocate buffer memory if none was passed to the function
|
||||||
|
image = (u8 *)malloc(utilGetSize(size));
|
||||||
|
if(image == NULL) {
|
||||||
|
#ifdef NO_FEX
|
||||||
|
fclose(f);
|
||||||
|
#else
|
||||||
|
fex_close(fe);
|
||||||
|
#endif
|
||||||
|
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||||
|
"data");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size = fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read image
|
||||||
|
int read = fileSize <= size ? fileSize : size; // do not read beyond file
|
||||||
|
#ifdef NO_FEX
|
||||||
|
int br = fread(image, 1, read, f);
|
||||||
|
const char* err = (br < read) ? "too few bytes from fread" : NULL;
|
||||||
|
fclose(f);
|
||||||
|
#else
|
||||||
|
err = fex_read(fe, image, read);
|
||||||
|
fex_close(fe);
|
||||||
|
#endif
|
||||||
|
if(err) {
|
||||||
|
systemMessage(MSG_ERROR_READING_IMAGE,
|
||||||
|
N_("Error reading image from %s: %s"), buffer, err);
|
||||||
|
if(data == NULL)
|
||||||
|
free(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = fileSize;
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void utilWriteInt(gzFile gzFile, int i)
|
void utilWriteInt(gzFile gzFile, int i)
|
||||||
@ -163,7 +614,7 @@ void utilWriteData(gzFile gzFile, variable_desc *data)
|
|||||||
|
|
||||||
gzFile utilGzOpen(const char *file, const char *mode)
|
gzFile utilGzOpen(const char *file, const char *mode)
|
||||||
{
|
{
|
||||||
utilGzWriteFunc = (int (ZEXPORT *)(void *,void * const, unsigned int))gzwrite;
|
utilGzWriteFunc = (int (ZEXPORT *)(gzFile, void * const, unsigned int))gzwrite;
|
||||||
utilGzReadFunc = gzread;
|
utilGzReadFunc = gzread;
|
||||||
utilGzCloseFunc = gzclose;
|
utilGzCloseFunc = gzclose;
|
||||||
utilGzSeekFunc = gzseek;
|
utilGzSeekFunc = gzseek;
|
||||||
@ -176,6 +627,7 @@ gzFile utilMemGzOpen(char *memory, int available, const char *mode)
|
|||||||
utilGzWriteFunc = memgzwrite;
|
utilGzWriteFunc = memgzwrite;
|
||||||
utilGzReadFunc = memgzread;
|
utilGzReadFunc = memgzread;
|
||||||
utilGzCloseFunc = memgzclose;
|
utilGzCloseFunc = memgzclose;
|
||||||
|
utilGzSeekFunc = memgzseek;
|
||||||
|
|
||||||
return memgzopen(memory, available, mode);
|
return memgzopen(memory, available, mode);
|
||||||
}
|
}
|
||||||
@ -204,3 +656,90 @@ long utilGzMemTell(gzFile file)
|
|||||||
{
|
{
|
||||||
return memtell(file);
|
return memtell(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void utilGBAFindSave(const u8 *data, const int size)
|
||||||
|
{
|
||||||
|
u32 *p = (u32 *)data;
|
||||||
|
u32 *end = (u32 *)(data + size);
|
||||||
|
int saveType = 0;
|
||||||
|
int flashSize = 0x10000;
|
||||||
|
bool rtcFound = false;
|
||||||
|
|
||||||
|
while(p < end) {
|
||||||
|
u32 d = READ32LE(p);
|
||||||
|
|
||||||
|
if(d == 0x52504545) {
|
||||||
|
if(memcmp(p, "EEPROM_", 7) == 0) {
|
||||||
|
if(saveType == 0)
|
||||||
|
saveType = 3;
|
||||||
|
}
|
||||||
|
} else if (d == 0x4D415253) {
|
||||||
|
if(memcmp(p, "SRAM_", 5) == 0) {
|
||||||
|
if(saveType == 0)
|
||||||
|
saveType = 1;
|
||||||
|
}
|
||||||
|
} else if (d == 0x53414C46) {
|
||||||
|
if(memcmp(p, "FLASH1M_", 8) == 0) {
|
||||||
|
if(saveType == 0) {
|
||||||
|
saveType = 2;
|
||||||
|
flashSize = 0x20000;
|
||||||
|
}
|
||||||
|
} else if(memcmp(p, "FLASH", 5) == 0) {
|
||||||
|
if(saveType == 0) {
|
||||||
|
saveType = 2;
|
||||||
|
flashSize = 0x10000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (d == 0x52494953) {
|
||||||
|
if(memcmp(p, "SIIRTC_V", 8) == 0)
|
||||||
|
rtcFound = true;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
// if no matches found, then set it to NONE
|
||||||
|
if(saveType == 0) {
|
||||||
|
saveType = 5;
|
||||||
|
}
|
||||||
|
rtcEnable(rtcFound);
|
||||||
|
cpuSaveType = saveType;
|
||||||
|
flashSetSize(flashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void utilUpdateSystemColorMaps(bool 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) 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) gbafilter_pal32(systemColorMap32, 0x10000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for existence of file.
|
||||||
|
bool utilFileExists( const char *filename )
|
||||||
|
{
|
||||||
|
FILE *f = fopen( filename, "r" );
|
||||||
|
if( f == NULL ) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
fclose( f );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,24 +1,5 @@
|
|||||||
// -*- C++ -*-
|
#ifndef UTIL_H
|
||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
#define UTIL_H
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
|
||||||
// Copyright (C) 2004 Forgotten and the VBA development team
|
|
||||||
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#ifndef VBA_UTIL_H
|
|
||||||
#define VBA_UTIL_H
|
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
|
||||||
@ -29,28 +10,47 @@ enum IMAGE_TYPE {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// save game
|
// save game
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *address;
|
void *address;
|
||||||
int size;
|
int size;
|
||||||
} variable_desc;
|
} variable_desc;
|
||||||
|
bool utilWritePNGFile(const char *, int, int, u8 *);
|
||||||
|
bool utilWriteBMPFile(const char *, int, int, u8 *);
|
||||||
|
void utilApplyIPS(const char *ips, uint8_t **rom, int *size);
|
||||||
|
bool utilIsGBAImage(const char *);
|
||||||
|
bool utilIsGBImage(const char *);
|
||||||
|
bool utilIsGzipFile(const char *);
|
||||||
|
void utilStripDoubleExtension(const char *, char *);
|
||||||
|
IMAGE_TYPE utilFindType(const char *);
|
||||||
|
uint8_t *utilLoad(const char *, bool (*)(const char*), uint8_t *, int &);
|
||||||
|
|
||||||
extern bool utilIsGBAImage(const char *);
|
void utilPutDword(uint8_t *, uint32_t);
|
||||||
extern bool utilIsGBImage(const char *);
|
void utilPutWord(uint8_t *, uint16_t);
|
||||||
extern bool utilIsZipFile(const char *);
|
void utilWriteData(gzFile, variable_desc *);
|
||||||
|
void utilReadData(gzFile, variable_desc *);
|
||||||
|
void utilReadDataSkip(gzFile, variable_desc *);
|
||||||
|
int utilReadInt(gzFile);
|
||||||
|
void utilWriteInt(gzFile, int);
|
||||||
|
gzFile utilGzOpen(const char *file, const char *mode);
|
||||||
|
gzFile utilMemGzOpen(char *memory, int available, const char *mode);
|
||||||
|
int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
|
||||||
|
int utilGzRead(gzFile file, voidp buffer, unsigned int len);
|
||||||
|
int utilGzClose(gzFile file);
|
||||||
|
z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence);
|
||||||
|
long utilGzMemTell(gzFile file);
|
||||||
|
void utilGBAFindSave(const u8 *, const int);
|
||||||
|
void utilUpdateSystemColorMaps(bool lcd = false);
|
||||||
|
bool utilFileExists( const char *filename );
|
||||||
|
|
||||||
extern void utilPutDword(u8 *, u32);
|
|
||||||
extern void utilPutWord(u8 *, u16);
|
#ifdef __LIBRETRO__
|
||||||
extern void utilWriteData(gzFile, variable_desc *);
|
void utilWriteIntMem(uint8_t *& data, int);
|
||||||
extern void utilReadData(gzFile, variable_desc *);
|
void utilWriteMem(uint8_t *& data, const void *in_data, unsigned size);
|
||||||
extern void utilReadDataSkip(gzFile, variable_desc *);
|
void utilWriteDataMem(uint8_t *& data, variable_desc *);
|
||||||
extern int utilReadInt(gzFile);
|
|
||||||
extern void utilWriteInt(gzFile, int);
|
int utilReadIntMem(const uint8_t *& data);
|
||||||
extern gzFile utilGzOpen(const char *file, const char *mode);
|
void utilReadMem(void *buf, const uint8_t *& data, unsigned size);
|
||||||
extern gzFile utilMemGzOpen(char *memory, int available, const char *mode);
|
void utilReadDataMem(const uint8_t *& data, variable_desc *);
|
||||||
extern int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
|
|
||||||
extern int utilGzRead(gzFile file, voidp buffer, unsigned int len);
|
|
||||||
extern int utilGzClose(gzFile file);
|
|
||||||
extern z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence);
|
|
||||||
extern long utilGzMemTell(gzFile file);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // UTIL_H
|
||||||
|
@ -29,7 +29,7 @@ int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
|
|||||||
|
|
||||||
Blip_Buffer::Blip_Buffer()
|
Blip_Buffer::Blip_Buffer()
|
||||||
{
|
{
|
||||||
factor_ = LONG_MAX;
|
factor_ = (blip_ulong)LONG_MAX;
|
||||||
buffer_ = 0;
|
buffer_ = 0;
|
||||||
buffer_size_ = 0;
|
buffer_size_ = 0;
|
||||||
sample_rate_ = 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
|
blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
|
||||||
{
|
{
|
||||||
double ratio = (double)(sample_rate_) / double(rate);
|
double ratio = (double) sample_rate_ / rate;
|
||||||
blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
|
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
|
assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
|
||||||
return (blip_resampled_time_t) factor;
|
return (blip_resampled_time_t) factor;
|
||||||
@ -226,17 +226,15 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d
|
|||||||
treble = 5.0;
|
treble = 5.0;
|
||||||
|
|
||||||
double const maxh = 4096.0;
|
double const maxh = 4096.0;
|
||||||
double const rolloff = pow( 10.0, treble / (maxh * 20.0 * (1.0 - cutoff)) );
|
double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
|
||||||
double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
|
double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
|
||||||
double const to_angle = PI / (2.0 * maxh * oversample);
|
double const to_angle = PI / 2 / maxh / oversample;
|
||||||
for ( int i = 0; i < count; i++ )
|
for ( int i = 0; i < count; i++ )
|
||||||
{
|
{
|
||||||
double angle = double(((i - count)<<1) + 1) * to_angle;
|
double angle = ((i - count) * 2 + 1) * to_angle;
|
||||||
double maxhAngle = maxh * angle;
|
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
|
||||||
double c = rolloff * cos( maxhAngle - angle ) - cos( maxhAngle );
|
double cos_nc_angle = cos( maxh * cutoff * angle );
|
||||||
double cos_nc_angle = cos( maxhAngle * cutoff );
|
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
|
||||||
double cos_nc1_angle = cos( maxhAngle * cutoff - angle );
|
|
||||||
|
|
||||||
double cos_angle = cos( angle );
|
double cos_angle = cos( angle );
|
||||||
|
|
||||||
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
|
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
|
||||||
@ -252,7 +250,7 @@ void blip_eq_t::generate( float* out, int count ) const
|
|||||||
{
|
{
|
||||||
// lower cutoff freq for narrow kernels with their wider transition band
|
// lower cutoff freq for narrow kernels with their wider transition band
|
||||||
// (8 points->1.49, 16 points->1.15)
|
// (8 points->1.49, 16 points->1.15)
|
||||||
double oversample = blip_res * 2.25 / double(count) + 0.85;
|
double oversample = blip_res * 2.25 / count + 0.85;
|
||||||
double half_rate = sample_rate * 0.5;
|
double half_rate = sample_rate * 0.5;
|
||||||
if ( cutoff_freq )
|
if ( cutoff_freq )
|
||||||
oversample = half_rate / cutoff_freq;
|
oversample = half_rate / cutoff_freq;
|
||||||
@ -270,9 +268,7 @@ void Blip_Synth_::adjust_impulse()
|
|||||||
{
|
{
|
||||||
// sum pairs for each phase and add error correction to end of first half
|
// sum pairs for each phase and add error correction to end of first half
|
||||||
int const size = impulses_size();
|
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;
|
int p2 = blip_res - 2 - p;
|
||||||
long error = kernel_unit;
|
long error = kernel_unit;
|
||||||
@ -294,11 +290,9 @@ void Blip_Synth_::adjust_impulse()
|
|||||||
|
|
||||||
void Blip_Synth_::treble_eq( blip_eq_t const& eq )
|
void Blip_Synth_::treble_eq( blip_eq_t const& eq )
|
||||||
{
|
{
|
||||||
int blipRes2 = blip_res >> 1;
|
float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
|
||||||
|
|
||||||
float fimpulse [blipRes2 * (blip_widest_impulse_ - 1) + blip_res * 2];
|
int const half_size = blip_res / 2 * (width - 1);
|
||||||
|
|
||||||
int const half_size = blipRes2 * (width - 1);
|
|
||||||
eq.generate( &fimpulse [blip_res], half_size );
|
eq.generate( &fimpulse [blip_res], half_size );
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -308,25 +302,25 @@ void Blip_Synth_::treble_eq( blip_eq_t const& eq )
|
|||||||
fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
|
fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
|
||||||
|
|
||||||
// starts at 0
|
// starts at 0
|
||||||
for ( i = 0; i < blip_res; ++i )
|
for ( i = 0; i < blip_res; i++ )
|
||||||
fimpulse [i] = 0.0f;
|
fimpulse [i] = 0.0f;
|
||||||
|
|
||||||
// find rescale factor
|
// find rescale factor
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
for ( i = 0; i < half_size; ++i )
|
for ( i = 0; i < half_size; i++ )
|
||||||
total += fimpulse [blip_res + i];
|
total += fimpulse [blip_res + i];
|
||||||
|
|
||||||
//double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
|
//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 = 37888.0; // allows treble to +5 dB
|
||||||
double const base_unit = 32768.0; // necessary for blip_unscaled to work
|
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;
|
kernel_unit = (long) base_unit;
|
||||||
|
|
||||||
// integrate, first difference, rescale, convert to int
|
// integrate, first difference, rescale, convert to int
|
||||||
double sum = 0.0;
|
double sum = 0.0;
|
||||||
double next = 0.0;
|
double next = 0.0;
|
||||||
int const size = this->impulses_size();
|
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 );
|
impulses [i] = (short) (int) floor( (next - sum) * rescale + 0.5 );
|
||||||
sum += fimpulse [i];
|
sum += fimpulse [i];
|
||||||
@ -361,7 +355,7 @@ void Blip_Synth_::volume_unit( double new_unit )
|
|||||||
// if unit is really small, might need to attenuate kernel
|
// if unit is really small, might need to attenuate kernel
|
||||||
while ( factor < 2.0 )
|
while ( factor < 2.0 )
|
||||||
{
|
{
|
||||||
++shift;
|
shift++;
|
||||||
factor *= 2.0;
|
factor *= 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +411,7 @@ long Blip_Buffer::read_samples( blip_sample_t* out_, long max_samples, int stere
|
|||||||
blip_long s = BLIP_READER_READ( reader );
|
blip_long s = BLIP_READER_READ( reader );
|
||||||
BLIP_READER_NEXT_IDX_( reader, bass, offset );
|
BLIP_READER_NEXT_IDX_( reader, bass, offset );
|
||||||
BLIP_CLAMP( s, s );
|
BLIP_CLAMP( s, s );
|
||||||
out [offset << 1] = (blip_sample_t) s;
|
out [offset * 2] = (blip_sample_t) s;
|
||||||
}
|
}
|
||||||
while ( ++offset );
|
while ( ++offset );
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count )
|
|||||||
int bufs_remain = bufs_size;
|
int bufs_remain = bufs_size;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ( buf->non_silent() && ( buf->echo == (bool)echo_phase ) )
|
if ( buf->non_silent() && ( buf->echo == !!echo_phase ) )
|
||||||
{
|
{
|
||||||
stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
|
stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
|
||||||
int const bass = BLIP_READER_BASS( *buf );
|
int const bass = BLIP_READER_BASS( *buf );
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
|
|
||||||
class Gb_Env : public Gb_Osc {
|
class Gb_Env : public Gb_Osc {
|
||||||
public:
|
public:
|
||||||
|
Gb_Env() : env_enabled(false), env_delay(0) {}
|
||||||
int env_delay;
|
int env_delay;
|
||||||
int volume;
|
int volume;
|
||||||
bool env_enabled;
|
bool env_enabled;
|
||||||
|
@ -1,79 +1,46 @@
|
|||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
|
||||||
// Copyright (C) 2004-2006 Forgotten and the VBA development team
|
|
||||||
// Copyright (C) 2007-2008 VBA-M development team and Shay Green
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "../System.h"
|
#include "Patch.h"
|
||||||
#include "memfile.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifdef __GNUC__
|
|
||||||
typedef off64_t __off64_t;
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#define _stricmp strcasecmp
|
#define _stricmp strcasecmp
|
||||||
#endif // ! _MSC_VER
|
#endif // ! _MSC_VER
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
static int readInt2(MFILE *f)
|
||||||
#define fseeko64 _fseeki64
|
{
|
||||||
#define ftello64 _ftelli64
|
|
||||||
typedef __int64 __off64_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined (MACOSX)
|
|
||||||
#define fseeko64 fseeko
|
|
||||||
#define ftello64 ftello
|
|
||||||
typedef off_t __off64_t;
|
|
||||||
#endif /* __APPLE__ || MACOSX */
|
|
||||||
|
|
||||||
static int readInt2(MFILE *f) {
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int c = memfgetc(f);
|
int c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if(c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
res = c;
|
res = c;
|
||||||
c = memfgetc(f);
|
c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if(c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
return c + (res << 8);
|
return c + (res<<8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readInt3(MFILE *f) {
|
static int readInt3(MFILE *f)
|
||||||
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int c = memfgetc(f);
|
int c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if(c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
res = c;
|
res = c;
|
||||||
c = memfgetc(f);
|
c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if(c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
res = c + (res << 8);
|
res = c + (res<<8);
|
||||||
c = memfgetc(f);
|
c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if(c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
return c + (res << 8);
|
return c + (res<<8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 readInt4(MFILE *f) {
|
static s64 readInt4(MFILE *f)
|
||||||
|
{
|
||||||
s64 tmp, res = 0;
|
s64 tmp, res = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@ -82,13 +49,14 @@ static s64 readInt4(MFILE *f) {
|
|||||||
if (c == MEOF)
|
if (c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
tmp = c;
|
tmp = c;
|
||||||
res = res + (tmp << (i * 8));
|
res = res + (tmp << (i*8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 readInt8(MFILE *f) {
|
static s64 readInt8(MFILE *f)
|
||||||
|
{
|
||||||
s64 tmp, res = 0;
|
s64 tmp, res = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@ -97,21 +65,20 @@ static s64 readInt8(MFILE *f) {
|
|||||||
if (c == MEOF)
|
if (c == MEOF)
|
||||||
return -1;
|
return -1;
|
||||||
tmp = c;
|
tmp = c;
|
||||||
res = res + (tmp << (i * 8));
|
res = res + (tmp << (i*8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 readVarPtr(MFILE *f) {
|
static s64 readVarPtr(MFILE *f)
|
||||||
|
{
|
||||||
s64 offset = 0, shift = 1;
|
s64 offset = 0, shift = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int c = memfgetc(f);
|
int c = memfgetc(f);
|
||||||
if (c == MEOF)
|
if (c == MEOF) return 0;
|
||||||
return 0;
|
|
||||||
offset += (c & 0x7F) * shift;
|
offset += (c & 0x7F) * shift;
|
||||||
if (c & 0x80)
|
if (c & 0x80) break;
|
||||||
break;
|
|
||||||
shift <<= 7;
|
shift <<= 7;
|
||||||
offset += shift;
|
offset += shift;
|
||||||
}
|
}
|
||||||
@ -122,7 +89,8 @@ static s64 readVarPtr(MFILE *f) {
|
|||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uLong computePatchCRC(MFILE *f, unsigned int size) {
|
static uLong computePatchCRC(MFILE *f, unsigned int size)
|
||||||
|
{
|
||||||
Bytef buf[4096];
|
Bytef buf[4096];
|
||||||
long readed;
|
long readed;
|
||||||
|
|
||||||
@ -132,71 +100,75 @@ static uLong computePatchCRC(MFILE *f, unsigned int size) {
|
|||||||
crc = crc32(crc, buf, readed);
|
crc = crc32(crc, buf, readed);
|
||||||
size -= readed;
|
size -= readed;
|
||||||
} while (readed > 0);
|
} while (readed > 0);
|
||||||
|
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool patchApplyIPS(MFILE * f, u8 **r, int *s) {
|
bool patchApplyIPS(MFILE *f, u8 **r, int *s)
|
||||||
|
{
|
||||||
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
u8 *rom = *r;
|
u8 *rom = *r;
|
||||||
int size = *s;
|
int size = *s;
|
||||||
if (memfgetc(f) == 'P' && memfgetc(f) == 'A' && memfgetc(f) == 'T'
|
if(memfgetc(f) == 'P' &&
|
||||||
&& memfgetc(f) == 'C' && memfgetc(f) == 'H') {
|
memfgetc(f) == 'A' &&
|
||||||
|
memfgetc(f) == 'T' &&
|
||||||
|
memfgetc(f) == 'C' &&
|
||||||
|
memfgetc(f) == 'H') {
|
||||||
int b;
|
int b;
|
||||||
int offset;
|
int offset;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
for (;;) {
|
for(;;) {
|
||||||
// read offset
|
// read offset
|
||||||
offset = readInt3(f);
|
offset = readInt3(f);
|
||||||
// if offset == MEOF, end of patch
|
// if offset == MEOF, end of patch
|
||||||
if (offset == 0x454f46 || offset == -1)
|
if(offset == 0x454f46 || offset == -1)
|
||||||
break;
|
break;
|
||||||
// read length
|
// read length
|
||||||
len = readInt2(f);
|
len = readInt2(f);
|
||||||
if (!len) {
|
if(!len) {
|
||||||
// len == 0, RLE block
|
// len == 0, RLE block
|
||||||
len = readInt2(f);
|
len = readInt2(f);
|
||||||
// byte to fill
|
// byte to fill
|
||||||
int c = memfgetc(f);
|
int c = memfgetc(f);
|
||||||
if (c == -1)
|
if(c == -1)
|
||||||
break;
|
break;
|
||||||
b = (u8) c;
|
b = (u8)c;
|
||||||
} else
|
} else
|
||||||
b = -1;
|
b= -1;
|
||||||
// check if we need to reallocate our ROM
|
// check if we need to reallocate our ROM
|
||||||
if ((offset + len) >= size) {
|
if((offset + len) >= size) {
|
||||||
#ifdef GEKKO
|
#ifdef GEKKO
|
||||||
size = offset + len;
|
size = offset + len;
|
||||||
#else
|
#else
|
||||||
size *= 2;
|
size *= 2;
|
||||||
rom = (u8 *) realloc(rom, size);
|
rom = (u8 *)realloc(rom, size);
|
||||||
#endif
|
#endif
|
||||||
*r = rom;
|
*r = rom;
|
||||||
*s = size;
|
*s = size;
|
||||||
}
|
}
|
||||||
if (b == -1) {
|
if(b == -1) {
|
||||||
// normal block, just read the data
|
// normal block, just read the data
|
||||||
if (memfread(&rom[offset], 1, len, f) != (size_t) len)
|
if(memfread(&rom[offset], 1, len, f) != (size_t)len)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// fill the region with the given byte
|
// fill the region with the given byte
|
||||||
while (len--) {
|
while(len--) {
|
||||||
rom[offset++] = b;
|
rom[offset++] = b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool patchApplyUPS(MFILE * f, u8 **rom, int *size) {
|
bool patchApplyUPS(MFILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
s64 srcCRC, dstCRC, patchCRC;
|
s64 srcCRC, dstCRC, patchCRC;
|
||||||
|
|
||||||
memfseek(f, 0, MSEEK_END);
|
memfseek(f, 0, MSEEK_END);
|
||||||
@ -206,9 +178,7 @@ bool patchApplyUPS(MFILE * f, u8 **rom, int *size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memfseek(f, 0, MSEEK_SET);
|
memfseek(f, 0, MSEEK_SET);
|
||||||
|
if(memfgetc(f) != 'U' || memfgetc(f) != 'P' || memfgetc(f) != 'S' || memfgetc(f) != '1') {
|
||||||
if (memfgetc(f) != 'U' || memfgetc(f) != 'P' || memfgetc(f) != 'S'
|
|
||||||
|| memfgetc(f) != '1') {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +191,7 @@ bool patchApplyUPS(MFILE * f, u8 **rom, int *size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memfseek(f, 0, MSEEK_SET);
|
memfseek(f, 0, MSEEK_SET);
|
||||||
u32 crc = computePatchCRC(f, patchSize - 4);
|
u32 crc = computePatchCRC(f, patchSize-4);
|
||||||
|
|
||||||
if (crc != patchCRC) {
|
if (crc != patchCRC) {
|
||||||
return false;
|
return false;
|
||||||
@ -236,67 +206,72 @@ bool patchApplyUPS(MFILE * f, u8 **rom, int *size) {
|
|||||||
s64 dstSize = readVarPtr(f);
|
s64 dstSize = readVarPtr(f);
|
||||||
|
|
||||||
if (crc == srcCRC) {
|
if (crc == srcCRC) {
|
||||||
dataSize = srcSize;
|
if (srcSize != *size) {
|
||||||
} else if (crc == dstCRC) {
|
return false;
|
||||||
|
}
|
||||||
dataSize = dstSize;
|
dataSize = dstSize;
|
||||||
|
} else if (crc == dstCRC) {
|
||||||
|
if (dstSize != *size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dataSize = srcSize;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (dataSize != *size) {
|
if (dataSize > *size) {
|
||||||
return false;
|
*rom = (u8*)realloc(*rom, dataSize);
|
||||||
|
memset(*rom + *size, 0, dataSize - *size);
|
||||||
|
*size = dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 relative = 0;
|
s64 relative = 0;
|
||||||
u8 *mem;
|
u8 *mem;
|
||||||
while (memftell(f) < patchSize - 12) {
|
while(memftell(f) < patchSize - 12) {
|
||||||
relative += readVarPtr(f);
|
relative += readVarPtr(f);
|
||||||
if (relative > dataSize)
|
if (relative > dataSize) continue;
|
||||||
continue;
|
|
||||||
mem = *rom + relative;
|
mem = *rom + relative;
|
||||||
for (s64 i = relative; i < dataSize; i++) {
|
for(s64 i = relative; i < dataSize; i++) {
|
||||||
int x = memfgetc(f);
|
int x = memfgetc(f);
|
||||||
relative++;
|
relative++;
|
||||||
if (!x)
|
if (!x) break;
|
||||||
break;
|
|
||||||
if (i < dataSize) {
|
if (i < dataSize) {
|
||||||
*mem++ ^= x;
|
*mem++ ^= x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ppfVersion(MFILE *f) {
|
static int ppfVersion(MFILE *f)
|
||||||
|
{
|
||||||
memfseek(f, 0, MSEEK_SET);
|
memfseek(f, 0, MSEEK_SET);
|
||||||
if (memfgetc(f) != 'P' || memfgetc(f) != 'P' || memfgetc(f) != 'F')
|
if (memfgetc(f) != 'P' || memfgetc(f) != 'P' || memfgetc(f) != 'F') //-V501
|
||||||
return 0;
|
|
||||||
switch (memfgetc(f)) {
|
|
||||||
case '1':
|
|
||||||
return 1;
|
|
||||||
case '2':
|
|
||||||
return 2;
|
|
||||||
case '3':
|
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return 0;
|
return 0;
|
||||||
|
switch(memfgetc(f)){
|
||||||
|
case '1': return 1;
|
||||||
|
case '2': return 2;
|
||||||
|
case '3': return 3;
|
||||||
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppfFileIdLen(MFILE *f, int version) {
|
static int ppfFileIdLen(MFILE *f, int version)
|
||||||
|
{
|
||||||
if (version == 2) {
|
if (version == 2) {
|
||||||
memfseek(f, -8, MSEEK_END);
|
memfseek(f, -8, MSEEK_END);
|
||||||
} else {
|
} else {
|
||||||
memfseek(f, -6, MSEEK_END);
|
memfseek(f, -6, MSEEK_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memfgetc(f) != '.' || memfgetc(f) != 'D' || memfgetc(f) != 'I'
|
if (memfgetc(f) != '.' || memfgetc(f) != 'D' || memfgetc(f) != 'I' || memfgetc(f) != 'Z')
|
||||||
|| memfgetc(f) != 'Z')
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (version == 2) ? readInt4(f) : readInt2(f);
|
return (version == 2) ? readInt4(f) : readInt2(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size) {
|
static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
memfseek(f, 0, MSEEK_END);
|
memfseek(f, 0, MSEEK_END);
|
||||||
int count = memftell(f);
|
int count = memftell(f);
|
||||||
if (count < 56)
|
if (count < 56)
|
||||||
@ -314,9 +289,9 @@ static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size) {
|
|||||||
int len = memfgetc(f);
|
int len = memfgetc(f);
|
||||||
if (len == MEOF)
|
if (len == MEOF)
|
||||||
break;
|
break;
|
||||||
if (offset + len > *size)
|
if (offset+len > *size)
|
||||||
break;
|
break;
|
||||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
if (memfread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
break;
|
break;
|
||||||
count -= 4 + 1 + len;
|
count -= 4 + 1 + len;
|
||||||
}
|
}
|
||||||
@ -324,12 +299,13 @@ static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size) {
|
|||||||
return (count == 0);
|
return (count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) {
|
static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
memfseek(f, 0, MSEEK_END);
|
memfseek(f, 0, MSEEK_END);
|
||||||
int count = memftell(f);
|
int count = memftell(f);
|
||||||
if (count < 56 + 4 + 1024)
|
if (count < 56+4+1024)
|
||||||
return false;
|
return false;
|
||||||
count -= 56 + 4 + 1024;
|
count -= 56+4+1024;
|
||||||
|
|
||||||
memfseek(f, 56, MSEEK_SET);
|
memfseek(f, 56, MSEEK_SET);
|
||||||
|
|
||||||
@ -348,7 +324,7 @@ static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) {
|
|||||||
if (idlen > 0)
|
if (idlen > 0)
|
||||||
count -= 16 + 16 + idlen;
|
count -= 16 + 16 + idlen;
|
||||||
|
|
||||||
memfseek(f, 56 + 4 + 1024, MSEEK_SET);
|
memfseek(f, 56+4+1024, MSEEK_SET);
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
int offset = readInt4(f);
|
int offset = readInt4(f);
|
||||||
@ -357,9 +333,9 @@ static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) {
|
|||||||
int len = memfgetc(f);
|
int len = memfgetc(f);
|
||||||
if (len == MEOF)
|
if (len == MEOF)
|
||||||
break;
|
break;
|
||||||
if (offset + len > *size)
|
if (offset+len > *size)
|
||||||
break;
|
break;
|
||||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
if (memfread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
break;
|
break;
|
||||||
count -= 4 + 1 + len;
|
count -= 4 + 1 + len;
|
||||||
}
|
}
|
||||||
@ -367,12 +343,13 @@ static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) {
|
|||||||
return (count == 0);
|
return (count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) {
|
static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size)
|
||||||
|
{
|
||||||
memfseek(f, 0, MSEEK_END);
|
memfseek(f, 0, MSEEK_END);
|
||||||
int count = memftell(f);
|
int count = memftell(f);
|
||||||
if (count < 56 + 4 + 1024)
|
if (count < 56+4+1024)
|
||||||
return false;
|
return false;
|
||||||
count -= 56 + 4;
|
count -= 56+4;
|
||||||
|
|
||||||
memfseek(f, 56, MSEEK_SET);
|
memfseek(f, 56, MSEEK_SET);
|
||||||
|
|
||||||
@ -395,7 +372,7 @@ static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) {
|
|||||||
if (idlen > 0)
|
if (idlen > 0)
|
||||||
count -= 16 + 16 + idlen;
|
count -= 16 + 16 + idlen;
|
||||||
|
|
||||||
memfseek(f, 56 + 4 + (blockcheck ? 1024 : 0), MSEEK_SET);
|
memfseek(f, 56+4+(blockcheck ? 1024 : 0), MSEEK_SET);
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
s64 offset = readInt8(f);
|
s64 offset = readInt8(f);
|
||||||
@ -404,15 +381,13 @@ static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) {
|
|||||||
int len = memfgetc(f);
|
int len = memfgetc(f);
|
||||||
if (len == MEOF)
|
if (len == MEOF)
|
||||||
break;
|
break;
|
||||||
if (offset + len > *size)
|
if (offset+len > *size)
|
||||||
break;
|
break;
|
||||||
if (memfread(&mem[offset], 1, len, f) != (size_t) len)
|
if (memfread(&mem[offset], 1, len, f) != (size_t)len)
|
||||||
break;
|
break;
|
||||||
if (undo)
|
if (undo) memfseek(f, len, MSEEK_CUR);
|
||||||
memfseek(f, len, MSEEK_CUR);
|
|
||||||
count -= 8 + 1 + len;
|
count -= 8 + 1 + len;
|
||||||
if (undo)
|
if (undo) count -= len;
|
||||||
count -= len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (count == 0);
|
return (count == 0);
|
||||||
@ -423,8 +398,7 @@ bool patchApplyPPF(MFILE *f, u8 **rom, int *size)
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
int version = ppfVersion(f);
|
int version = ppfVersion(f);
|
||||||
switch (version)
|
switch (version) {
|
||||||
{
|
|
||||||
case 1: res = patchApplyPPF1(f, rom, size); break;
|
case 1: res = patchApplyPPF1(f, rom, size); break;
|
||||||
case 2: res = patchApplyPPF2(f, rom, size); break;
|
case 2: res = patchApplyPPF2(f, rom, size); break;
|
||||||
case 3: res = patchApplyPPF3(f, rom, size); break;
|
case 3: res = patchApplyPPF3(f, rom, size); break;
|
||||||
|
@ -1,31 +1,12 @@
|
|||||||
// -*- C++ -*-
|
#ifndef PATCH_H
|
||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
#define PATCH_H
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
|
||||||
// Copyright (C) 2004 Forgotten and the VBA development team
|
|
||||||
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#ifndef VBA_PATCH_H
|
|
||||||
#define VBA_PATCH_H
|
|
||||||
|
|
||||||
#include "memfile.h"
|
#include "memfile.h"
|
||||||
#include "System.h"
|
#include "Types.h"
|
||||||
|
|
||||||
bool applyPatch(const char *patchname, u8 **rom, int *size);
|
bool applyPatch(const char *patchname, u8 **rom, int *size);
|
||||||
bool patchApplyIPS(MFILE * f, u8 **r, int *s);
|
bool patchApplyIPS(MFILE * f, u8 **r, int *s);
|
||||||
bool patchApplyUPS(MFILE * f, u8 **rom, int *size);
|
bool patchApplyUPS(MFILE * f, u8 **rom, int *size);
|
||||||
bool patchApplyPPF(MFILE *f, u8 **rom, int *size);
|
bool patchApplyPPF(MFILE *f, u8 **rom, int *size);
|
||||||
|
|
||||||
#endif
|
#endif // PATCH_H
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
// -*- C++ -*-
|
#ifndef PORT_H
|
||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
#define PORT_H
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
|
||||||
// Copyright (C) 2004 Forgotten and the VBA development team
|
|
||||||
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
#ifdef __CELLOS_LV2__
|
||||||
// it under the terms of the GNU General Public License as published by
|
/* PlayStation3 */
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
#include <ppu_intrinsics.h>
|
||||||
// any later version.
|
#endif
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
#ifndef VBA_PORT_H
|
#ifdef _XBOX360
|
||||||
#define VBA_PORT_H
|
/* XBox 360 */
|
||||||
|
#include <ppcintrinsics.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
// swaps a 16-bit value
|
// swaps a 16-bit value
|
||||||
static inline u16 swap16(u16 v)
|
static inline u16 swap16(u16 v)
|
||||||
@ -72,4 +65,4 @@ static inline u32 swap32(u32 v)
|
|||||||
*((u32 *)x) = (v)
|
*((u32 *)x) = (v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // PORT_H
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#ifndef __VBA_SOUND_DRIVER_H__
|
#ifndef __VBA_SOUND_DRIVER_H__
|
||||||
#define __VBA_SOUND_DRIVER_H__
|
#define __VBA_SOUND_DRIVER_H__
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#ifndef __VBA_TYPES_H__
|
#ifndef __VBA_TYPES_H__
|
||||||
#define __VBA_TYPES_H__
|
#define __VBA_TYPES_H__
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Adapted from original gzio.c from zlib library by Forgotten
|
* Adapted from original gzio.c from zlib library by Forgotten
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* @(#) $Id: memgzio.c,v 1.5 2006/06/06 21:04:20 spacy51 Exp $ */
|
/* @(#) $Id: memgzio.c 1213 2013-09-21 13:57:40Z kode54 $ */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -697,3 +697,23 @@ long ZEXPORT memtell(file)
|
|||||||
|
|
||||||
return memTell(s->file);
|
return memTell(s->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
z_off_t ZEXPORT memgzseek(gzFile file, z_off_t off, int whence)
|
||||||
|
{
|
||||||
|
char buf[80];
|
||||||
|
|
||||||
|
if(whence != SEEK_CUR) {
|
||||||
|
fputs("FIXME: memgzio does not support seeking\n", stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is inefficient, but the best I can do without actually reading
|
||||||
|
// the above code
|
||||||
|
while(off > 0) {
|
||||||
|
int r = memgzread(file, buf, off > 80 ? 80 : off);
|
||||||
|
if(r <= 0)
|
||||||
|
return -1;
|
||||||
|
off -= r;
|
||||||
|
}
|
||||||
|
return memtell(file);
|
||||||
|
}
|
||||||
|
@ -19,5 +19,6 @@ int ZEXPORT memgzread(gzFile file, voidp buf, unsigned len);
|
|||||||
int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len);
|
int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len);
|
||||||
int ZEXPORT memgzclose(gzFile file);
|
int ZEXPORT memgzclose(gzFile file);
|
||||||
long ZEXPORT memtell(gzFile file);
|
long ZEXPORT memtell(gzFile file);
|
||||||
|
z_off_t ZEXPORT memgzseek(gzFile file, z_off_t off, int whence);
|
||||||
|
|
||||||
#endif // MEMGZIO_H
|
#endif // MEMGZIO_H
|
||||||
|
@ -17,7 +17,12 @@ typedef union {
|
|||||||
u16 W;
|
u16 W;
|
||||||
} gbRegister;
|
} gbRegister;
|
||||||
|
|
||||||
|
extern gbRegister AF, BC, DE, HL, SP, PC;
|
||||||
|
extern u16 IFF;
|
||||||
|
int gbDis(char *, u16);
|
||||||
|
|
||||||
bool gbLoadRom(const char *);
|
bool gbLoadRom(const char *);
|
||||||
|
bool gbUpdateSizes();
|
||||||
void gbEmulate(int);
|
void gbEmulate(int);
|
||||||
void gbWriteMemory(register u16, register u8);
|
void gbWriteMemory(register u16, register u8);
|
||||||
void gbDrawLine();
|
void gbDrawLine();
|
||||||
@ -38,8 +43,11 @@ bool gbWritePNGFile(const char *);
|
|||||||
bool gbWriteBMPFile(const char *);
|
bool gbWriteBMPFile(const char *);
|
||||||
bool gbReadGSASnapshot(const char *);
|
bool gbReadGSASnapshot(const char *);
|
||||||
|
|
||||||
|
extern int gbHardware;
|
||||||
|
|
||||||
extern struct EmulatedSystem GBSystem;
|
extern struct EmulatedSystem GBSystem;
|
||||||
|
|
||||||
|
// For VBA-GX
|
||||||
bool MemgbReadBatteryFile(char * membuffer, int read);
|
bool MemgbReadBatteryFile(char * membuffer, int read);
|
||||||
int MemgbWriteBatteryFile(char * membuffer);
|
int MemgbWriteBatteryFile(char * membuffer);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include <string.h>
|
#include <cstdlib>
|
||||||
#include "../common/Types.h"
|
#include "../common/Types.h"
|
||||||
|
|
||||||
u8 *gbMemoryMap[16];
|
u8 *gbMemoryMap[16];
|
||||||
@ -30,7 +30,7 @@ u16 gbColorFilter[32768];
|
|||||||
int gbColorOption = 0;
|
int gbColorOption = 0;
|
||||||
int gbPaletteOption = 0;
|
int gbPaletteOption = 0;
|
||||||
int gbEmulatorType = 0;
|
int gbEmulatorType = 0;
|
||||||
int gbBorderOn = 1;
|
int gbBorderOn = 0;
|
||||||
int gbBorderAutomatic = 0;
|
int gbBorderAutomatic = 0;
|
||||||
int gbBorderLineSkip = 160;
|
int gbBorderLineSkip = 160;
|
||||||
int gbBorderRowSkip = 0;
|
int gbBorderRowSkip = 0;
|
||||||
@ -38,3 +38,4 @@ int gbBorderColumnSkip = 0;
|
|||||||
int gbDmaTicks = 0;
|
int gbDmaTicks = 0;
|
||||||
|
|
||||||
u8 (*gbSerialFunction)(u8) = NULL;
|
u8 (*gbSerialFunction)(u8) = NULL;
|
||||||
|
void (*sgbBorderListener)(bool) = NULL;
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
#include "gb.h"
|
#include "gb.h"
|
||||||
u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
const u8 gbDisabledRam [8] = {0x80, 0xff, 0xf0, 0x00, 0x30, 0xbf, 0xbf, 0xbf};
|
const u8 gbDisabledRam [8] = {0x80, 0xff, 0xf0, 0x00, 0x30, 0xbf, 0xbf, 0xbf};
|
||||||
extern int gbHardware;
|
|
||||||
extern int gbGBCColorType;
|
extern int gbGBCColorType;
|
||||||
extern gbRegister PC;
|
extern gbRegister PC;
|
||||||
|
|
||||||
|
// for UTC offset
|
||||||
|
#include "../../vbagx.h"
|
||||||
|
|
||||||
mapperMBC1 gbDataMBC1 = {
|
mapperMBC1 gbDataMBC1 = {
|
||||||
0, // RAM enable
|
0, // RAM enable
|
||||||
1, // ROM bank
|
1, // ROM bank
|
||||||
@ -327,7 +329,7 @@ mapperMBC3 gbDataMBC3 = {
|
|||||||
|
|
||||||
void memoryUpdateMBC3Clock()
|
void memoryUpdateMBC3Clock()
|
||||||
{
|
{
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL) - (GCSettings.OffsetMinutesUTC*60);
|
||||||
time_t diff = now - gbDataMBC3.mapperLastTime;
|
time_t diff = now - gbDataMBC3.mapperLastTime;
|
||||||
if(diff > 0) {
|
if(diff > 0) {
|
||||||
// update the clock according to the last update time
|
// update the clock according to the last update time
|
||||||
@ -437,6 +439,7 @@ void mapperMBC3RAM(u16 address, u8 value)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
time(&gbDataMBC3.mapperLastTime);
|
time(&gbDataMBC3.mapperLastTime);
|
||||||
|
gbDataMBC3.mapperLastTime -= (GCSettings.OffsetMinutesUTC*60);
|
||||||
switch(gbDataMBC3.mapperClockRegister) {
|
switch(gbDataMBC3.mapperClockRegister) {
|
||||||
case 0x08:
|
case 0x08:
|
||||||
gbDataMBC3.mapperSeconds = value;
|
gbDataMBC3.mapperSeconds = value;
|
||||||
@ -540,7 +543,6 @@ mapperMBC5 gbDataMBC5 = {
|
|||||||
0 // is rumble cartridge?
|
0 // is rumble cartridge?
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int ConfigRequested;
|
|
||||||
// MBC5 ROM write registers
|
// MBC5 ROM write registers
|
||||||
void mapperMBC5ROM(u16 address, u8 value)
|
void mapperMBC5ROM(u16 address, u8 value)
|
||||||
{
|
{
|
||||||
@ -581,18 +583,10 @@ void mapperMBC5ROM(u16 address, u8 value)
|
|||||||
gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x4000: // RAM bank select, plus rumble
|
case 0x4000: // RAM bank select
|
||||||
// Some games support rumble, such as Disney Tarzan, but aren't on a
|
if(gbDataMBC5.isRumbleCartridge)
|
||||||
// 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;
|
value &= 0x07;
|
||||||
} else if (gbRamSizeMask <= 0x7FFF) {
|
else
|
||||||
systemPossibleCartridgeRumble(value & 0x08);
|
|
||||||
value &= 0x07;
|
|
||||||
} else
|
|
||||||
value &= 0x0f;
|
value &= 0x0f;
|
||||||
if(value == gbDataMBC5.mapperRAMBank)
|
if(value == gbDataMBC5.mapperRAMBank)
|
||||||
break;
|
break;
|
||||||
@ -1231,7 +1225,7 @@ void memoryUpdateTAMA5Clock()
|
|||||||
else
|
else
|
||||||
gbDaysinMonth[1] = 28;
|
gbDaysinMonth[1] = 28;
|
||||||
|
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL) - (GCSettings.OffsetMinutesUTC*60);
|
||||||
time_t diff = now - gbDataTAMA5.mapperLastTime;
|
time_t diff = now - gbDataTAMA5.mapperLastTime;
|
||||||
if(diff > 0) {
|
if(diff > 0) {
|
||||||
// update the clock according to the last update time
|
// update the clock according to the last update time
|
||||||
@ -1428,6 +1422,7 @@ void mapperTAMA5RAM(u16 address, u8 value)
|
|||||||
gbTAMA5ram[0x94] = MonthsH*16+MonthsL; // incorrect ? (not used by the game) ?
|
gbTAMA5ram[0x94] = MonthsH*16+MonthsL; // incorrect ? (not used by the game) ?
|
||||||
|
|
||||||
time(&gbDataTAMA5.mapperLastTime);
|
time(&gbDataTAMA5.mapperLastTime);
|
||||||
|
gbDataMBC3.mapperLastTime -= (GCSettings.OffsetMinutesUTC*60);
|
||||||
|
|
||||||
gbMemoryMap[0xa][0] = 1;
|
gbMemoryMap[0xa][0] = 1;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ void gbPrinterReset()
|
|||||||
void gbPrinterShowData()
|
void gbPrinterShowData()
|
||||||
{
|
{
|
||||||
systemGbPrint(gbPrinterData,
|
systemGbPrint(gbPrinterData,
|
||||||
|
gbPrinterDataCount,
|
||||||
gbPrinterPacket[6],
|
gbPrinterPacket[6],
|
||||||
gbPrinterPacket[7],
|
gbPrinterPacket[7],
|
||||||
gbPrinterPacket[8],
|
gbPrinterPacket[8],
|
||||||
@ -87,6 +88,7 @@ void gbPrinterShowData()
|
|||||||
|
|
||||||
void gbPrinterReceiveData()
|
void gbPrinterReceiveData()
|
||||||
{
|
{
|
||||||
|
int i = gbPrinterDataCount;
|
||||||
if(gbPrinterPacket[3]) { // compressed
|
if(gbPrinterPacket[3]) { // compressed
|
||||||
u8 *data = &gbPrinterPacket[6];
|
u8 *data = &gbPrinterPacket[6];
|
||||||
u8 *dest = &gbPrinterData[gbPrinterDataCount];
|
u8 *dest = &gbPrinterData[gbPrinterDataCount];
|
||||||
@ -97,16 +99,17 @@ void gbPrinterReceiveData()
|
|||||||
control &= 0x7f;
|
control &= 0x7f;
|
||||||
control += 2;
|
control += 2;
|
||||||
memset(dest, *data++, control);
|
memset(dest, *data++, control);
|
||||||
len += control;
|
len += 2;
|
||||||
dest += control;
|
dest += control;
|
||||||
} else { // raw data
|
} else { // raw data
|
||||||
control++;
|
control++;
|
||||||
memcpy(dest, data, control);
|
memcpy(dest, data, control);
|
||||||
dest += control;
|
dest += control;
|
||||||
data += control;
|
data += control;
|
||||||
len += control;
|
len += control + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gbPrinterDataCount = (int)(dest - gbPrinterData);
|
||||||
} else {
|
} else {
|
||||||
memcpy(&gbPrinterData[gbPrinterDataCount],
|
memcpy(&gbPrinterData[gbPrinterDataCount],
|
||||||
&gbPrinterPacket[6],
|
&gbPrinterPacket[6],
|
||||||
|
@ -40,7 +40,7 @@ u8 gbSgbScreenBuffer[4160];
|
|||||||
|
|
||||||
inline void gbSgbDraw24Bit(u8 *p, u16 v)
|
inline void gbSgbDraw24Bit(u8 *p, u16 v)
|
||||||
{
|
{
|
||||||
*((u32*) p) = systemColorMap32[v];
|
memcpy(p, &systemColorMap32[v], 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void gbSgbDraw32Bit(u32 *p, u16 v)
|
inline void gbSgbDraw32Bit(u32 *p, u16 v)
|
||||||
@ -188,9 +188,9 @@ void gbSgbRenderScreenToBuffer()
|
|||||||
|
|
||||||
void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
|
void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
|
||||||
{
|
{
|
||||||
u16 *dest = (u16*)pix + ((y+1) * (256+2)) + x;
|
u16 *dest = (u16*)pix + (y * (256+2)) + x;
|
||||||
u8 *dest8 = (u8*)pix + ((y*256)+x)*3;
|
u8 *dest8 = (u8*)pix + ((y*256)+x)*3;
|
||||||
u32 *dest32 = (u32*)pix + ((y+1)*257) + x;
|
u32 *dest32 = (u32*)pix + (y*257) + x;
|
||||||
|
|
||||||
u8 *tileAddress = &gbSgbBorderChar[tile * 32];
|
u8 *tileAddress = &gbSgbBorderChar[tile * 32];
|
||||||
u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
|
u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
#include "../Util.h"
|
#include "../Util.h"
|
||||||
#include "gbGlobals.h"
|
#include "gbGlobals.h"
|
||||||
#include "gbSound.h"
|
#include "gbSound.h"
|
||||||
|
#include "gb.h"
|
||||||
|
|
||||||
#include "../apu/Gb_Apu.h"
|
#include "../apu/Gb_Apu.h"
|
||||||
#include "../apu/Effects_Buffer.h"
|
#include "../apu/Effects_Buffer.h"
|
||||||
|
|
||||||
extern int gbHardware;
|
|
||||||
extern long soundSampleRate; // current sound quality
|
extern long soundSampleRate; // current sound quality
|
||||||
|
|
||||||
gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false };
|
gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false };
|
||||||
@ -121,6 +121,13 @@ static void reset_apu()
|
|||||||
|
|
||||||
static void remake_stereo_buffer()
|
static void remake_stereo_buffer()
|
||||||
{
|
{
|
||||||
|
// APU
|
||||||
|
if ( !gb_apu )
|
||||||
|
{
|
||||||
|
gb_apu = new Gb_Apu; // TODO: handle errors
|
||||||
|
reset_apu();
|
||||||
|
}
|
||||||
|
|
||||||
// Stereo_Buffer
|
// Stereo_Buffer
|
||||||
delete stereo_buffer;
|
delete stereo_buffer;
|
||||||
stereo_buffer = 0;
|
stereo_buffer = 0;
|
||||||
@ -129,19 +136,14 @@ static void remake_stereo_buffer()
|
|||||||
if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory
|
if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory
|
||||||
stereo_buffer->clock_rate( gb_apu->clock_rate );
|
stereo_buffer->clock_rate( gb_apu->clock_rate );
|
||||||
|
|
||||||
// APU
|
// Multi_Buffer
|
||||||
static int const chan_types [chan_count] = {
|
static int const chan_types [chan_count] = {
|
||||||
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
|
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
|
||||||
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
|
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
|
||||||
};
|
};
|
||||||
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors
|
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors
|
||||||
|
|
||||||
if ( !gb_apu )
|
// Volume Level
|
||||||
{
|
|
||||||
gb_apu = new Gb_Apu; // TODO: handle errors
|
|
||||||
reset_apu();
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_effects();
|
apply_effects();
|
||||||
apply_volume();
|
apply_volume();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include <string.h>
|
#ifndef __LIBRETRO__
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -910,24 +910,24 @@ int cheatsCheckKeys(u32 keys, u32 extended)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GSA_8_BIT_POINTER :
|
case GSA_8_BIT_POINTER :
|
||||||
if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
|
if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
|
||||||
(CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
|
((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
|
||||||
{
|
{
|
||||||
CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
|
CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
|
||||||
cheatsList[i].value & 0xFF);
|
cheatsList[i].value & 0xFF);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GSA_16_BIT_POINTER :
|
case GSA_16_BIT_POINTER :
|
||||||
if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
|
if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
|
||||||
(CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
|
((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
|
||||||
{
|
{
|
||||||
CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
|
CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
|
||||||
cheatsList[i].value & 0xFFFF);
|
cheatsList[i].value & 0xFFFF);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GSA_32_BIT_POINTER :
|
case GSA_32_BIT_POINTER :
|
||||||
if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
|
if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
|
||||||
(CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
|
((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
|
||||||
{
|
{
|
||||||
CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
|
CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
@ -935,15 +935,15 @@ int cheatsCheckKeys(u32 keys, u32 extended)
|
|||||||
break;
|
break;
|
||||||
case GSA_8_BIT_ADD :
|
case GSA_8_BIT_ADD :
|
||||||
CPUWriteByte(cheatsList[i].address,
|
CPUWriteByte(cheatsList[i].address,
|
||||||
(cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address) & 0xFF);
|
((cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address)) & 0xFF);
|
||||||
break;
|
break;
|
||||||
case GSA_16_BIT_ADD :
|
case GSA_16_BIT_ADD :
|
||||||
CPUWriteHalfWord(cheatsList[i].address,
|
CPUWriteHalfWord(cheatsList[i].address,
|
||||||
(cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address) & 0xFFFF);
|
((cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address)) & 0xFFFF);
|
||||||
break;
|
break;
|
||||||
case GSA_32_BIT_ADD :
|
case GSA_32_BIT_ADD :
|
||||||
CPUWriteMemory(cheatsList[i].address ,
|
CPUWriteMemory(cheatsList[i].address ,
|
||||||
cheatsList[i].value + CPUReadMemory(cheatsList[i].address) & 0xFFFFFFFF);
|
(cheatsList[i].value + CPUReadMemory(cheatsList[i].address)) & 0xFFFFFFFF);
|
||||||
break;
|
break;
|
||||||
case GSA_8_BIT_IF_LOWER_U:
|
case GSA_8_BIT_IF_LOWER_U:
|
||||||
if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
|
if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
|
||||||
@ -2678,8 +2678,6 @@ void cheatsReadGameSkip( gzFile file, int version )
|
|||||||
utilGzSeek( file, sizeof( cheatsList ), SEEK_CUR );
|
utilGzSeek( file, sizeof( cheatsList ), SEEK_CUR );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool firstCodeBreaker = true;
|
|
||||||
|
|
||||||
for( int i = 0; i < nCheats; i++ ) {
|
for( int i = 0; i < nCheats; i++ ) {
|
||||||
if( version < 9 ) {
|
if( version < 9 ) {
|
||||||
utilGzSeek( file, ( 7 * sizeof(int) ) + ( 52 * sizeof(char) ), SEEK_CUR );
|
utilGzSeek( file, ( 7 * sizeof(int) ) + ( 52 * sizeof(char) ), SEEK_CUR );
|
||||||
@ -2898,3 +2896,4 @@ void cheatsWriteByte(u32, u8)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -9,7 +9,15 @@ int eepromMode = EEPROM_IDLE;
|
|||||||
int eepromByte = 0;
|
int eepromByte = 0;
|
||||||
int eepromBits = 0;
|
int eepromBits = 0;
|
||||||
int eepromAddress = 0;
|
int eepromAddress = 0;
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
// Workaround for broken-by-design GBA save semantics
|
||||||
|
extern u8 libretro_save_buf[0x20000 + 0x2000];
|
||||||
|
u8 *eepromData = libretro_save_buf + 0x20000;
|
||||||
|
#else
|
||||||
u8 eepromData[0x2000];
|
u8 eepromData[0x2000];
|
||||||
|
#endif
|
||||||
|
|
||||||
u8 eepromBuffer[16];
|
u8 eepromBuffer[16];
|
||||||
bool eepromInUse = false;
|
bool eepromInUse = false;
|
||||||
int eepromSize = 512;
|
int eepromSize = 512;
|
||||||
@ -27,7 +35,11 @@ variable_desc eepromSaveData[] = {
|
|||||||
|
|
||||||
void eepromInit()
|
void eepromInit()
|
||||||
{
|
{
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
memset(eepromData, 255, 0x2000);
|
||||||
|
#else
|
||||||
memset(eepromData, 255, sizeof(eepromData));
|
memset(eepromData, 255, sizeof(eepromData));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void eepromReset()
|
void eepromReset()
|
||||||
@ -40,6 +52,26 @@ void eepromReset()
|
|||||||
eepromSize = 512;
|
eepromSize = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void eepromSaveGame(uint8_t *& data)
|
||||||
|
{
|
||||||
|
utilWriteDataMem(data, eepromSaveData);
|
||||||
|
utilWriteIntMem(data, eepromSize);
|
||||||
|
utilWriteMem(data, eepromData, 0x2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eepromReadGame(const uint8_t *& data, int version)
|
||||||
|
{
|
||||||
|
utilReadDataMem(data, eepromSaveData);
|
||||||
|
if (version >= SAVE_GAME_VERSION_3) {
|
||||||
|
eepromSize = utilReadIntMem(data);
|
||||||
|
utilReadMem(eepromData, data, 0x2000);
|
||||||
|
} else {
|
||||||
|
// prior to 0.7.1, only 4K EEPROM was supported
|
||||||
|
eepromSize = 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
void eepromSaveGame(gzFile gzFile)
|
void eepromSaveGame(gzFile gzFile)
|
||||||
{
|
{
|
||||||
utilWriteData(gzFile, eepromSaveData);
|
utilWriteData(gzFile, eepromSaveData);
|
||||||
@ -68,6 +100,7 @@ void eepromReadGameSkip(gzFile gzFile, int version)
|
|||||||
utilGzSeek(gzFile, 0x2000, SEEK_CUR);
|
utilGzSeek(gzFile, 0x2000, SEEK_CUR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int eepromRead(u32 /* address */)
|
int eepromRead(u32 /* address */)
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
#ifndef EEPROM_H
|
#ifndef EEPROM_H
|
||||||
#define EEPROM_H
|
#define EEPROM_H
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
extern void eepromSaveGame(u8* &data);
|
||||||
|
extern void eepromReadGame(const u8 *&data, int version);
|
||||||
|
#else
|
||||||
extern void eepromSaveGame(gzFile _gzFile);
|
extern void eepromSaveGame(gzFile _gzFile);
|
||||||
extern void eepromReadGame(gzFile _gzFile, int version);
|
extern void eepromReadGame(gzFile _gzFile, int version);
|
||||||
|
#endif
|
||||||
extern void eepromReadGameSkip(gzFile _gzFile, int version);
|
extern void eepromReadGameSkip(gzFile _gzFile, int version);
|
||||||
extern int eepromRead(u32 address);
|
extern int eepromRead(u32 address);
|
||||||
extern void eepromWrite(u32 address, u8 value);
|
extern void eepromWrite(u32 address, u8 value);
|
||||||
extern void eepromInit();
|
extern void eepromInit();
|
||||||
extern void eepromReset();
|
extern void eepromReset();
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
extern u8 *eepromData;
|
||||||
|
#else
|
||||||
extern u8 eepromData[0x2000];
|
extern u8 eepromData[0x2000];
|
||||||
|
#endif
|
||||||
extern bool eepromInUse;
|
extern bool eepromInUse;
|
||||||
extern int eepromSize;
|
extern int eepromSize;
|
||||||
|
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
#define FLASH_PROGRAM 8
|
#define FLASH_PROGRAM 8
|
||||||
#define FLASH_SETBANK 9
|
#define FLASH_SETBANK 9
|
||||||
|
|
||||||
u8 flashSaveMemory[0x20000];
|
#ifdef __LIBRETRO__
|
||||||
|
extern uint8_t libretro_save_buf[0x20000 + 0x2000];
|
||||||
|
uint8_t *flashSaveMemory = libretro_save_buf;
|
||||||
|
#else
|
||||||
|
uint8_t flashSaveMemory[FLASH_128K_SZ];
|
||||||
|
#endif
|
||||||
|
|
||||||
int flashState = FLASH_READ_ARRAY;
|
int flashState = FLASH_READ_ARRAY;
|
||||||
int flashReadState = FLASH_READ_ARRAY;
|
int flashReadState = FLASH_READ_ARRAY;
|
||||||
int flashSize = 0x10000;
|
int flashSize = 0x10000;
|
||||||
@ -51,7 +57,11 @@ static variable_desc flashSaveData3[] = {
|
|||||||
|
|
||||||
void flashInit()
|
void flashInit()
|
||||||
{
|
{
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
memset(flashSaveMemory, 0xff, 0x20000);
|
||||||
|
#else
|
||||||
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
|
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void flashReset()
|
void flashReset()
|
||||||
@ -61,6 +71,17 @@ void flashReset()
|
|||||||
flashBank = 0;
|
flashBank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void flashSaveGame(uint8_t *& data)
|
||||||
|
{
|
||||||
|
utilWriteDataMem(data, flashSaveData3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashReadGame(const uint8_t *& data, int)
|
||||||
|
{
|
||||||
|
utilReadDataMem(data, flashSaveData3);
|
||||||
|
}
|
||||||
|
#else
|
||||||
void flashSaveGame(gzFile gzFile)
|
void flashSaveGame(gzFile gzFile)
|
||||||
{
|
{
|
||||||
utilWriteData(gzFile, flashSaveData3);
|
utilWriteData(gzFile, flashSaveData3);
|
||||||
@ -90,6 +111,8 @@ void flashReadGameSkip(gzFile gzFile, int version)
|
|||||||
utilReadDataSkip(gzFile, flashSaveData3);
|
utilReadDataSkip(gzFile, flashSaveData3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void flashSetSize(int size)
|
void flashSetSize(int size)
|
||||||
{
|
{
|
||||||
|
@ -1,13 +1,24 @@
|
|||||||
#ifndef FLASH_H
|
#ifndef FLASH_H
|
||||||
#define FLASH_H
|
#define FLASH_H
|
||||||
|
|
||||||
|
#define FLASH_128K_SZ 0x20000
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
extern void flashSaveGame(u8 *& data);
|
||||||
|
extern void flashReadGame(const u8 *& data, int);
|
||||||
|
#else
|
||||||
extern void flashSaveGame(gzFile _gzFile);
|
extern void flashSaveGame(gzFile _gzFile);
|
||||||
extern void flashReadGame(gzFile _gzFile, int version);
|
extern void flashReadGame(gzFile _gzFile, int version);
|
||||||
|
#endif
|
||||||
extern void flashReadGameSkip(gzFile _gzFile, int version);
|
extern void flashReadGameSkip(gzFile _gzFile, int version);
|
||||||
extern u8 flashRead(u32 address);
|
extern u8 flashRead(u32 address);
|
||||||
extern void flashWrite(u32 address, u8 byte);
|
extern void flashWrite(u32 address, u8 byte);
|
||||||
extern void flashDelayedWrite(u32 address, u8 byte);
|
extern void flashDelayedWrite(u32 address, u8 byte);
|
||||||
extern u8 flashSaveMemory[0x20000];
|
#ifdef __LIBRETRO__
|
||||||
|
extern uint8_t *flashSaveMemory;
|
||||||
|
#else
|
||||||
|
extern u8 flashSaveMemory[FLASH_128K_SZ];
|
||||||
|
#endif
|
||||||
extern void flashSaveDecide(u32 address, u8 byte);
|
extern void flashSaveDecide(u32 address, u8 byte);
|
||||||
extern void flashReset();
|
extern void flashReset();
|
||||||
extern void flashSetSize(int size);
|
extern void flashSetSize(int size);
|
||||||
|
@ -297,7 +297,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#define EMIT0(op) #op"; "
|
#define EMIT0(op) #op"; "
|
||||||
#define EMIT1(op,arg) #op" "arg"; "
|
#define EMIT1(op,arg) #op" "arg"; "
|
||||||
#define EMIT2(op,src,dest) #op" "src", "dest"; "
|
#define EMIT2(op,src,dest) #op" "src", "dest"; "
|
||||||
#define CONST(val) "$"#val
|
#define KONST(val) "$"#val
|
||||||
#define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
|
#define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
|
||||||
#define ASMVAR2(prefix,cvar) STRING (prefix) cvar
|
#define ASMVAR2(prefix,cvar) STRING (prefix) cvar
|
||||||
#define STRING(x) #x
|
#define STRING(x) #x
|
||||||
@ -330,7 +330,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#define EMIT0(op) __asm op
|
#define EMIT0(op) __asm op
|
||||||
#define EMIT1(op,arg) __asm op arg
|
#define EMIT1(op,arg) __asm op arg
|
||||||
#define EMIT2(op,src,dest) __asm op dest, src
|
#define EMIT2(op,src,dest) __asm op dest, src
|
||||||
#define CONST(val) val
|
#define KONST(val) val
|
||||||
#define VAR(var) var
|
#define VAR(var) var
|
||||||
#define VARL(var) dword ptr var
|
#define VARL(var) dword ptr var
|
||||||
#define REGREF1(index) reg[index]
|
#define REGREF1(index) reg[index]
|
||||||
@ -349,15 +349,19 @@ static void count(u32 opcode, int cond_res)
|
|||||||
|
|
||||||
// Helper macros for loading value / shift count
|
// Helper macros for loading value / shift count
|
||||||
#define VALUE_LOAD_IMM \
|
#define VALUE_LOAD_IMM \
|
||||||
EMIT2(and, CONST(0x0F), eax) \
|
EMIT2(and, KONST(0x0F), eax) \
|
||||||
EMIT2(mov, REGREF2(eax,4), eax) \
|
EMIT2(mov, REGREF2(eax,4), eax) \
|
||||||
EMIT2(shr, CONST(7), ecx) \
|
EMIT2(shr, KONST(7), ecx) \
|
||||||
EMIT2(and, CONST(0x1F), ecx)
|
EMIT2(and, KONST(0x1F), ecx)
|
||||||
#define VALUE_LOAD_REG \
|
#define VALUE_LOAD_REG \
|
||||||
EMIT2(and, CONST(0x0F), eax) \
|
EMIT2(and, KONST(0x0F), eax) \
|
||||||
|
EMIT2(cmp, KONST(0x0F), eax) \
|
||||||
EMIT2(mov, REGREF2(eax,4), eax) \
|
EMIT2(mov, REGREF2(eax,4), eax) \
|
||||||
|
EMIT1(jne, LABELREF(3,f)) \
|
||||||
|
EMIT2(add, KONST(4), eax) \
|
||||||
|
LABEL(3) \
|
||||||
EMIT2(movzx, ch, ecx) \
|
EMIT2(movzx, ch, ecx) \
|
||||||
EMIT2(and, CONST(0x0F), ecx) \
|
EMIT2(and, KONST(0x0F), ecx) \
|
||||||
EMIT2(mov, REGREF2(ecx,4), ecx)
|
EMIT2(mov, REGREF2(ecx,4), ecx)
|
||||||
|
|
||||||
// Helper macros for setting flags
|
// Helper macros for setting flags
|
||||||
@ -381,13 +385,13 @@ static void count(u32 opcode, int cond_res)
|
|||||||
ALU_HEADER \
|
ALU_HEADER \
|
||||||
LOAD_C_FLAG \
|
LOAD_C_FLAG \
|
||||||
EMIT2(mov, ecx, edx) \
|
EMIT2(mov, ecx, edx) \
|
||||||
EMIT2(shr, CONST(14), edx) \
|
EMIT2(shr, KONST(14), edx) \
|
||||||
EMIT2(mov, ecx, eax) \
|
EMIT2(mov, ecx, eax) \
|
||||||
EMIT2(mov, ecx, esi) \
|
EMIT2(mov, ecx, esi) \
|
||||||
EMIT2(shr, CONST(10), esi) \
|
EMIT2(shr, KONST(10), esi) \
|
||||||
EMIT2(and, CONST(0x3C), edx) \
|
EMIT2(and, KONST(0x3C), edx) \
|
||||||
EMIT2(mov, REGREF1(edx), edx) \
|
EMIT2(mov, REGREF1(edx), edx) \
|
||||||
EMIT2(and, CONST(0x3C), esi)
|
EMIT2(and, KONST(0x3C), esi)
|
||||||
|
|
||||||
#define LOAD_C_FLAG_YES EMIT2(mov, VAR(C_FLAG), bl)
|
#define LOAD_C_FLAG_YES EMIT2(mov, VAR(C_FLAG), bl)
|
||||||
#define LOAD_C_FLAG_NO /*nothing*/
|
#define LOAD_C_FLAG_NO /*nothing*/
|
||||||
@ -415,14 +419,14 @@ static void count(u32 opcode, int cond_res)
|
|||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(test, cl, cl) \
|
EMIT2(test, cl, cl) \
|
||||||
EMIT1(jz, LABELREF(0,f)) \
|
EMIT1(jz, LABELREF(0,f)) \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(je, LABELREF(1,f)) \
|
EMIT1(je, LABELREF(1,f)) \
|
||||||
EMIT1(ja, LABELREF(2,f)) \
|
EMIT1(ja, LABELREF(2,f)) \
|
||||||
EMIT2(shl, cl, eax) \
|
EMIT2(shl, cl, eax) \
|
||||||
EMIT1(setc, bl) \
|
EMIT1(setc, bl) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(test, CONST(1), al) \
|
EMIT2(test, KONST(1), al) \
|
||||||
EMIT1(setnz, bl) \
|
EMIT1(setnz, bl) \
|
||||||
EMIT2(xor, eax, eax) \
|
EMIT2(xor, eax, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
@ -432,7 +436,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
LABEL(0)
|
LABEL(0)
|
||||||
#define VALUE_LSL_REG_NC \
|
#define VALUE_LSL_REG_NC \
|
||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(jae, LABELREF(1,f)) \
|
EMIT1(jae, LABELREF(1,f)) \
|
||||||
EMIT2(shl, cl, eax) \
|
EMIT2(shl, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
@ -466,7 +470,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(test, cl, cl) \
|
EMIT2(test, cl, cl) \
|
||||||
EMIT1(jz, LABELREF(0,f)) \
|
EMIT1(jz, LABELREF(0,f)) \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(je, LABELREF(1,f)) \
|
EMIT1(je, LABELREF(1,f)) \
|
||||||
EMIT1(ja, LABELREF(2,f)) \
|
EMIT1(ja, LABELREF(2,f)) \
|
||||||
EMIT2(shr, cl, eax) \
|
EMIT2(shr, cl, eax) \
|
||||||
@ -483,7 +487,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
LABEL(0)
|
LABEL(0)
|
||||||
#define VALUE_LSR_REG_NC \
|
#define VALUE_LSR_REG_NC \
|
||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(jae, LABELREF(1,f)) \
|
EMIT1(jae, LABELREF(1,f)) \
|
||||||
EMIT2(shr, cl, eax) \
|
EMIT2(shr, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
@ -499,7 +503,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT1(setc, bl) \
|
EMIT1(setc, bl) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(sar, CONST(31), eax) \
|
EMIT2(sar, KONST(31), eax) \
|
||||||
EMIT1(sets, bl) \
|
EMIT1(sets, bl) \
|
||||||
LABEL(0)
|
LABEL(0)
|
||||||
#define VALUE_ASR_IMM_NC \
|
#define VALUE_ASR_IMM_NC \
|
||||||
@ -508,7 +512,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT2(sar, cl, eax) \
|
EMIT2(sar, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(sar, CONST(31), eax) \
|
EMIT2(sar, KONST(31), eax) \
|
||||||
LABEL(0)
|
LABEL(0)
|
||||||
|
|
||||||
// OP Rd,Rb,Rm ASR Rs
|
// OP Rd,Rb,Rm ASR Rs
|
||||||
@ -516,23 +520,23 @@ static void count(u32 opcode, int cond_res)
|
|||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(test, cl, cl) \
|
EMIT2(test, cl, cl) \
|
||||||
EMIT1(jz, LABELREF(0,f)) \
|
EMIT1(jz, LABELREF(0,f)) \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(jae, LABELREF(1,f)) \
|
EMIT1(jae, LABELREF(1,f)) \
|
||||||
EMIT2(sar, cl, eax) \
|
EMIT2(sar, cl, eax) \
|
||||||
EMIT1(setc, bl) \
|
EMIT1(setc, bl) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(sar, CONST(31), eax) \
|
EMIT2(sar, KONST(31), eax) \
|
||||||
EMIT1(sets, bl) \
|
EMIT1(sets, bl) \
|
||||||
LABEL(0)
|
LABEL(0)
|
||||||
#define VALUE_ASR_REG_NC \
|
#define VALUE_ASR_REG_NC \
|
||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(cmp, CONST(0x20), cl) \
|
EMIT2(cmp, KONST(0x20), cl) \
|
||||||
EMIT1(jae, LABELREF(1,f)) \
|
EMIT1(jae, LABELREF(1,f)) \
|
||||||
EMIT2(sar, cl, eax) \
|
EMIT2(sar, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(sar, CONST(31), eax) \
|
EMIT2(sar, KONST(31), eax) \
|
||||||
LABEL(0)
|
LABEL(0)
|
||||||
|
|
||||||
// OP Rd,Rb,Rm ROR #
|
// OP Rd,Rb,Rm ROR #
|
||||||
@ -542,8 +546,8 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT2(ror, cl, eax) \
|
EMIT2(ror, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(bt, CONST(0), ebx) \
|
EMIT2(bt, KONST(0), ebx) \
|
||||||
EMIT2(rcr, CONST(1), eax) \
|
EMIT2(rcr, KONST(1), eax) \
|
||||||
LABEL(0) \
|
LABEL(0) \
|
||||||
EMIT1(setc, bl)
|
EMIT1(setc, bl)
|
||||||
#define VALUE_ROR_IMM_NC \
|
#define VALUE_ROR_IMM_NC \
|
||||||
@ -552,14 +556,14 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT2(ror, cl, eax) \
|
EMIT2(ror, cl, eax) \
|
||||||
EMIT1(jmp, LABELREF(0,f)) \
|
EMIT1(jmp, LABELREF(0,f)) \
|
||||||
LABEL(1) \
|
LABEL(1) \
|
||||||
EMIT2(bt, CONST(0), VARL(C_FLAG)) \
|
EMIT2(bt, KONST(0), VARL(C_FLAG)) \
|
||||||
EMIT2(rcr, CONST(1), eax) \
|
EMIT2(rcr, KONST(1), eax) \
|
||||||
LABEL(0)
|
LABEL(0)
|
||||||
|
|
||||||
// OP Rd,Rb,Rm ROR Rs
|
// OP Rd,Rb,Rm ROR Rs
|
||||||
#define VALUE_ROR_REG_C \
|
#define VALUE_ROR_REG_C \
|
||||||
VALUE_LOAD_REG \
|
VALUE_LOAD_REG \
|
||||||
EMIT2(bt, CONST(0), ebx) \
|
EMIT2(bt, KONST(0), ebx) \
|
||||||
EMIT2(ror, cl, eax) \
|
EMIT2(ror, cl, eax) \
|
||||||
EMIT1(setc, bl)
|
EMIT1(setc, bl)
|
||||||
#define VALUE_ROR_REG_NC \
|
#define VALUE_ROR_REG_NC \
|
||||||
@ -571,7 +575,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT2(movzx, ch, ecx) \
|
EMIT2(movzx, ch, ecx) \
|
||||||
EMIT2(add, ecx, ecx) \
|
EMIT2(add, ecx, ecx) \
|
||||||
EMIT2(movzx, al, eax) \
|
EMIT2(movzx, al, eax) \
|
||||||
EMIT2(bt, CONST(0), ebx) \
|
EMIT2(bt, KONST(0), ebx) \
|
||||||
EMIT2(ror, cl, eax) \
|
EMIT2(ror, cl, eax) \
|
||||||
EMIT1(setc, bl)
|
EMIT1(setc, bl)
|
||||||
#define VALUE_IMM_NC \
|
#define VALUE_IMM_NC \
|
||||||
@ -584,7 +588,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
|
|
||||||
// Set condition codes iff the destination register is not R15 (PC)
|
// Set condition codes iff the destination register is not R15 (PC)
|
||||||
#define CHECK_PC(OP, SETCOND) \
|
#define CHECK_PC(OP, SETCOND) \
|
||||||
EMIT2(cmp, CONST(0x3C), esi) \
|
EMIT2(cmp, KONST(0x3C), esi) \
|
||||||
EMIT1(je, LABELREF(8,f)) \
|
EMIT1(je, LABELREF(8,f)) \
|
||||||
OP SETCOND \
|
OP SETCOND \
|
||||||
EMIT1(jmp, LABELREF(9,f)) \
|
EMIT1(jmp, LABELREF(9,f)) \
|
||||||
@ -613,18 +617,18 @@ static void count(u32 opcode, int cond_res)
|
|||||||
EMIT2(mov, edx, REGREF1(esi))
|
EMIT2(mov, edx, REGREF1(esi))
|
||||||
#define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD)
|
#define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD)
|
||||||
#define OP_ADC \
|
#define OP_ADC \
|
||||||
EMIT2(bt, CONST(0), VARL(C_FLAG)) \
|
EMIT2(bt, KONST(0), VARL(C_FLAG)) \
|
||||||
EMIT2(adc, eax, edx) \
|
EMIT2(adc, eax, edx) \
|
||||||
EMIT2(mov, edx, REGREF1(esi))
|
EMIT2(mov, edx, REGREF1(esi))
|
||||||
#define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD)
|
#define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD)
|
||||||
#define OP_SBC \
|
#define OP_SBC \
|
||||||
EMIT2(bt, CONST(0), VARL(C_FLAG)) \
|
EMIT2(bt, KONST(0), VARL(C_FLAG)) \
|
||||||
EMIT0(cmc) \
|
EMIT0(cmc) \
|
||||||
EMIT2(sbb, eax, edx) \
|
EMIT2(sbb, eax, edx) \
|
||||||
EMIT2(mov, edx, REGREF1(esi))
|
EMIT2(mov, edx, REGREF1(esi))
|
||||||
#define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB)
|
#define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB)
|
||||||
#define OP_RSC \
|
#define OP_RSC \
|
||||||
EMIT2(bt, CONST(0), VARL(C_FLAG)) \
|
EMIT2(bt, KONST(0), VARL(C_FLAG)) \
|
||||||
EMIT0(cmc) \
|
EMIT0(cmc) \
|
||||||
EMIT2(sbb, edx, eax) \
|
EMIT2(sbb, edx, eax) \
|
||||||
EMIT2(mov, eax, REGREF1(esi))
|
EMIT2(mov, eax, REGREF1(esi))
|
||||||
@ -656,7 +660,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#define OP_MVN \
|
#define OP_MVN \
|
||||||
EMIT1(not, eax) \
|
EMIT1(not, eax) \
|
||||||
EMIT2(mov, eax, REGREF1(esi))
|
EMIT2(mov, eax, REGREF1(esi))
|
||||||
#define OP_MVNS CHECK_PC(OP_MVN, SETCOND_LOGICAL)
|
#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL)
|
||||||
|
|
||||||
// ALU cleanup macro
|
// ALU cleanup macro
|
||||||
#define ALU_FINISH ALU_TRAILER
|
#define ALU_FINISH ALU_TRAILER
|
||||||
@ -677,7 +681,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
: "0" (offset), "c" (shift));
|
: "0" (offset), "c" (shift));
|
||||||
|
|
||||||
#define RRX_OFFSET \
|
#define RRX_OFFSET \
|
||||||
asm(EMIT2(btl,CONST(0),VAR(C_FLAG)) \
|
asm(EMIT2(btl,KONST(0),VAR(C_FLAG)) \
|
||||||
"rcr $1, %0" \
|
"rcr $1, %0" \
|
||||||
: "=r" (offset) \
|
: "=r" (offset) \
|
||||||
: "0" (offset));
|
: "0" (offset));
|
||||||
@ -752,27 +756,31 @@ static void count(u32 opcode, int cond_res)
|
|||||||
// OP Rd,Rb,Rm LSL Rs
|
// OP Rd,Rb,Rm LSL Rs
|
||||||
#ifndef VALUE_LSL_REG_C
|
#ifndef VALUE_LSL_REG_C
|
||||||
#define VALUE_LSL_REG_C \
|
#define VALUE_LSL_REG_C \
|
||||||
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
u32 shift = reg[(opcode >> 8)&15].B.B0; \
|
||||||
|
u32 rm = reg[opcode & 0x0F].I; \
|
||||||
|
if((opcode & 0x0F) == 15) { \
|
||||||
|
rm += 4; \
|
||||||
|
} \
|
||||||
if (LIKELY(shift)) { \
|
if (LIKELY(shift)) { \
|
||||||
if (shift == 32) { \
|
if (shift == 32) { \
|
||||||
value = 0; \
|
value = 0; \
|
||||||
C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\
|
C_OUT = (rm & 1 ? true : false); \
|
||||||
} else if (LIKELY(shift < 32)) { \
|
} else if (LIKELY(shift < 32)) { \
|
||||||
u32 v = reg[opcode & 0x0F].I; \
|
u32 v = rm; \
|
||||||
C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
|
C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
|
||||||
value = v << shift; \
|
value = v << shift; \
|
||||||
} else { \
|
} else { \
|
||||||
value = 0; \
|
value = 0; \
|
||||||
C_OUT = false; \
|
C_OUT = false; \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
value = reg[opcode & 0x0F].I; \
|
value = rm; \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// OP Rd,Rb,Rm LSR #
|
// OP Rd,Rb,Rm LSR #
|
||||||
#ifndef VALUE_LSR_IMM_C
|
#ifndef VALUE_LSR_IMM_C
|
||||||
#define VALUE_LSR_IMM_C \
|
#define VALUE_LSR_IMM_C \
|
||||||
unsigned int shift = (opcode >> 7) & 0x1F; \
|
u32 shift = (opcode >> 7) & 0x1F; \
|
||||||
if (LIKELY(shift)) { \
|
if (LIKELY(shift)) { \
|
||||||
u32 v = reg[opcode & 0x0F].I; \
|
u32 v = reg[opcode & 0x0F].I; \
|
||||||
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
|
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
|
||||||
@ -786,12 +794,16 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#ifndef VALUE_LSR_REG_C
|
#ifndef VALUE_LSR_REG_C
|
||||||
#define VALUE_LSR_REG_C \
|
#define VALUE_LSR_REG_C \
|
||||||
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
||||||
|
u32 rm = reg[opcode & 0x0F].I; \
|
||||||
|
if((opcode & 0x0F) == 15) { \
|
||||||
|
rm += 4; \
|
||||||
|
} \
|
||||||
if (LIKELY(shift)) { \
|
if (LIKELY(shift)) { \
|
||||||
if (shift == 32) { \
|
if (shift == 32) { \
|
||||||
value = 0; \
|
value = 0; \
|
||||||
C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
|
C_OUT = (rm & 0x80000000 ? true : false);\
|
||||||
} else if (LIKELY(shift < 32)) { \
|
} else if (LIKELY(shift < 32)) { \
|
||||||
u32 v = reg[opcode & 0x0F].I; \
|
u32 v = rm; \
|
||||||
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
|
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
|
||||||
value = v >> shift; \
|
value = v >> shift; \
|
||||||
} else { \
|
} else { \
|
||||||
@ -799,7 +811,7 @@ static void count(u32 opcode, int cond_res)
|
|||||||
C_OUT = false; \
|
C_OUT = false; \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
value = reg[opcode & 0x0F].I; \
|
value = rm; \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// OP Rd,Rb,Rm ASR #
|
// OP Rd,Rb,Rm ASR #
|
||||||
@ -825,13 +837,17 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#ifndef VALUE_ASR_REG_C
|
#ifndef VALUE_ASR_REG_C
|
||||||
#define VALUE_ASR_REG_C \
|
#define VALUE_ASR_REG_C \
|
||||||
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
||||||
|
u32 rm = reg[opcode & 0x0F].I; \
|
||||||
|
if((opcode & 0x0F) == 15) { \
|
||||||
|
rm += 4; \
|
||||||
|
} \
|
||||||
if (LIKELY(shift < 32)) { \
|
if (LIKELY(shift < 32)) { \
|
||||||
if (LIKELY(shift)) { \
|
if (LIKELY(shift)) { \
|
||||||
s32 v = reg[opcode & 0x0F].I; \
|
s32 v = rm; \
|
||||||
C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
|
C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
|
||||||
value = v >> (int)shift; \
|
value = v >> (int)shift; \
|
||||||
} else { \
|
} else { \
|
||||||
value = reg[opcode & 0x0F].I; \
|
value = rm; \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
if (reg[opcode & 0x0F].I & 0x80000000) { \
|
if (reg[opcode & 0x0F].I & 0x80000000) { \
|
||||||
@ -863,13 +879,17 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#ifndef VALUE_ROR_REG_C
|
#ifndef VALUE_ROR_REG_C
|
||||||
#define VALUE_ROR_REG_C \
|
#define VALUE_ROR_REG_C \
|
||||||
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
|
||||||
|
u32 rm = reg[opcode & 0x0F].I; \
|
||||||
|
if((opcode & 0x0F) == 15) { \
|
||||||
|
rm += 4; \
|
||||||
|
} \
|
||||||
if (LIKELY(shift & 0x1F)) { \
|
if (LIKELY(shift & 0x1F)) { \
|
||||||
u32 v = reg[opcode & 0x0F].I; \
|
u32 v = rm; \
|
||||||
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
|
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
|
||||||
value = ((v << (32 - shift)) | \
|
value = ((v << (32 - shift)) | \
|
||||||
(v >> shift)); \
|
(v >> shift)); \
|
||||||
} else { \
|
} else { \
|
||||||
value = reg[opcode & 0x0F].I; \
|
value = rm; \
|
||||||
if (shift) \
|
if (shift) \
|
||||||
C_OUT = (value & 0x80000000 ? true : false);\
|
C_OUT = (value & 0x80000000 ? true : false);\
|
||||||
}
|
}
|
||||||
@ -950,9 +970,9 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#endif
|
#endif
|
||||||
#ifndef OP_RSB
|
#ifndef OP_RSB
|
||||||
#define OP_RSB \
|
#define OP_RSB \
|
||||||
u32 lhs = reg[(opcode>>16)&15].I; \
|
u32 lhs = value; \
|
||||||
u32 rhs = value; \
|
u32 rhs = reg[(opcode>>16)&15].I; \
|
||||||
u32 res = rhs - lhs; \
|
u32 res = lhs - rhs; \
|
||||||
reg[dest].I = res;
|
reg[dest].I = res;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OP_RSBS
|
#ifndef OP_RSBS
|
||||||
@ -990,9 +1010,9 @@ static void count(u32 opcode, int cond_res)
|
|||||||
#endif
|
#endif
|
||||||
#ifndef OP_RSC
|
#ifndef OP_RSC
|
||||||
#define OP_RSC \
|
#define OP_RSC \
|
||||||
u32 lhs = reg[(opcode>>16)&15].I; \
|
u32 lhs = value; \
|
||||||
u32 rhs = value; \
|
u32 rhs = reg[(opcode>>16)&15].I; \
|
||||||
u32 res = rhs - lhs - !((u32)C_FLAG); \
|
u32 res = lhs - rhs - !((u32)C_FLAG); \
|
||||||
reg[dest].I = res;
|
reg[dest].I = res;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OP_RSCS
|
#ifndef OP_RSCS
|
||||||
@ -1516,7 +1536,7 @@ static INSN_REGPARM void arm121(u32 opcode)
|
|||||||
#define OP_LDR reg[dest].I = CPUReadMemory(address)
|
#define OP_LDR reg[dest].I = CPUReadMemory(address)
|
||||||
#define OP_LDRH reg[dest].I = CPUReadHalfWord(address)
|
#define OP_LDRH reg[dest].I = CPUReadHalfWord(address)
|
||||||
#define OP_LDRB reg[dest].I = CPUReadByte(address)
|
#define OP_LDRB reg[dest].I = CPUReadByte(address)
|
||||||
#define OP_LDRSH reg[dest].I = (s16)CPUReadHalfWordSigned(address)
|
#define OP_LDRSH reg[dest].I = (u32)CPUReadHalfWordSigned(address)
|
||||||
#define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address)
|
#define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address)
|
||||||
|
|
||||||
#define WRITEBACK_NONE /*nothing*/
|
#define WRITEBACK_NONE /*nothing*/
|
||||||
@ -2591,8 +2611,7 @@ static INSN_REGPARM void armA00(u32 opcode)
|
|||||||
reg[15].I += 4;
|
reg[15].I += 4;
|
||||||
ARM_PREFETCH;
|
ARM_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||||
+ codeTicksAccessSeq32(armNextPC);
|
|
||||||
busPrefetchCount = 0;
|
busPrefetchCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2608,8 +2627,7 @@ static INSN_REGPARM void armB00(u32 opcode)
|
|||||||
reg[15].I += 4;
|
reg[15].I += 4;
|
||||||
ARM_PREFETCH;
|
ARM_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||||
+ codeTicksAccessSeq32(armNextPC);
|
|
||||||
busPrefetchCount = 0;
|
busPrefetchCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2628,8 +2646,7 @@ static INSN_REGPARM void armE01(u32 opcode)
|
|||||||
static INSN_REGPARM void armF00(u32 opcode)
|
static INSN_REGPARM void armF00(u32 opcode)
|
||||||
{
|
{
|
||||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||||
+ codeTicksAccessSeq32(armNextPC);
|
|
||||||
busPrefetchCount = 0;
|
busPrefetchCount = 0;
|
||||||
CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
|
CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
|
||||||
}
|
}
|
||||||
@ -2681,9 +2698,9 @@ static insnfunc_t armInsnTable[4096] = {
|
|||||||
arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0
|
arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0
|
||||||
arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8
|
arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8
|
||||||
arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
|
arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
|
||||||
arm0E0,arm0E9,arm0E2,arm_UI,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
|
arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
|
||||||
arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
|
arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
|
||||||
arm0F0,arm0F9,arm0F2,arm_UI,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
|
arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
|
||||||
|
|
||||||
arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
|
arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
|
||||||
arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
|
arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
|
||||||
|
@ -300,7 +300,7 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
#else
|
#else
|
||||||
#define EMIT1(op,arg) #op" "arg"; "
|
#define EMIT1(op,arg) #op" "arg"; "
|
||||||
#define EMIT2(op,src,dest) #op" "src", "dest"; "
|
#define EMIT2(op,src,dest) #op" "src", "dest"; "
|
||||||
#define CONST(val) "$"#val
|
#define KONST(val) "$"#val
|
||||||
#define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
|
#define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
|
||||||
#define ASMVAR2(prefix,cvar) STRING (prefix) cvar
|
#define ASMVAR2(prefix,cvar) STRING (prefix) cvar
|
||||||
#define STRING(x) #x
|
#define STRING(x) #x
|
||||||
@ -327,7 +327,7 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
: \
|
: \
|
||||||
: "r" (value), "r" (reg[dest].I):"1");
|
: "r" (value), "r" (reg[dest].I):"1");
|
||||||
#define ADC_RD_RS \
|
#define ADC_RD_RS \
|
||||||
asm (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
|
asm (EMIT2(bt,KONST(0),VAR(C_FLAG)) \
|
||||||
"adc %1, %%ebx;"\
|
"adc %1, %%ebx;"\
|
||||||
EMIT1(setsb, VAR(N_FLAG)) \
|
EMIT1(setsb, VAR(N_FLAG)) \
|
||||||
EMIT1(setzb, VAR(Z_FLAG)) \
|
EMIT1(setzb, VAR(Z_FLAG)) \
|
||||||
@ -345,7 +345,7 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
: "=m" (reg[(d)].I));
|
: "=m" (reg[(d)].I));
|
||||||
#define MOV_RN_O8(d) \
|
#define MOV_RN_O8(d) \
|
||||||
asm ("andl $0xFF, %%eax;"\
|
asm ("andl $0xFF, %%eax;"\
|
||||||
EMIT2(movb,CONST(0),VAR(N_FLAG)) \
|
EMIT2(movb,KONST(0),VAR(N_FLAG)) \
|
||||||
"movl %%eax, %0;"\
|
"movl %%eax, %0;"\
|
||||||
EMIT1(setzb, VAR(Z_FLAG)) \
|
EMIT1(setzb, VAR(Z_FLAG)) \
|
||||||
: "=m" (reg[(d)].I));
|
: "=m" (reg[(d)].I));
|
||||||
@ -359,7 +359,7 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
: \
|
: \
|
||||||
: "m" (reg[(d)].I));
|
: "m" (reg[(d)].I));
|
||||||
#define SBC_RD_RS \
|
#define SBC_RD_RS \
|
||||||
asm volatile (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
|
asm volatile (EMIT2(bt,KONST(0),VAR(C_FLAG)) \
|
||||||
"cmc;"\
|
"cmc;"\
|
||||||
"sbb %1, %%ebx;"\
|
"sbb %1, %%ebx;"\
|
||||||
EMIT1(setsb, VAR(N_FLAG)) \
|
EMIT1(setsb, VAR(N_FLAG)) \
|
||||||
@ -464,9 +464,9 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
EMIT1(setcb, VAR(C_FLAG)) \
|
EMIT1(setcb, VAR(C_FLAG)) \
|
||||||
EMIT1(setob, VAR(V_FLAG))
|
EMIT1(setob, VAR(V_FLAG))
|
||||||
#define ADD_RD_RS_O3_0(N) \
|
#define ADD_RD_RS_O3_0(N) \
|
||||||
EMIT2(movb,CONST(0),VAR(C_FLAG)) \
|
EMIT2(movb,KONST(0),VAR(C_FLAG)) \
|
||||||
"add $0,%%ecx;" \
|
"add $0,%%ecx;" \
|
||||||
EMIT2(movb,CONST(0),VAR(V_FLAG))
|
EMIT2(movb,KONST(0),VAR(V_FLAG))
|
||||||
#define SUB_RD_RS_RN(N) \
|
#define SUB_RD_RS_RN(N) \
|
||||||
EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
|
EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
|
||||||
EMIT1(setncb, VAR(C_FLAG)) \
|
EMIT1(setncb, VAR(C_FLAG)) \
|
||||||
@ -476,9 +476,9 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
|
|||||||
EMIT1(setncb, VAR(C_FLAG)) \
|
EMIT1(setncb, VAR(C_FLAG)) \
|
||||||
EMIT1(setob, VAR(V_FLAG))
|
EMIT1(setob, VAR(V_FLAG))
|
||||||
#define SUB_RD_RS_O3_0(N) \
|
#define SUB_RD_RS_O3_0(N) \
|
||||||
EMIT2(movb,CONST(1),VAR(C_FLAG)) \
|
EMIT2(movb,KONST(1),VAR(C_FLAG)) \
|
||||||
"sub $0,%%ecx;" \
|
"sub $0,%%ecx;" \
|
||||||
EMIT2(movb,CONST(0),VAR(V_FLAG))
|
EMIT2(movb,KONST(0),VAR(V_FLAG))
|
||||||
#endif
|
#endif
|
||||||
#else // !__GNUC__
|
#else // !__GNUC__
|
||||||
#define ADD_RD_RS_RN(N) \
|
#define ADD_RD_RS_RN(N) \
|
||||||
@ -1416,10 +1416,18 @@ static INSN_REGPARM void thumb45_3(u32 opcode)
|
|||||||
CMP_RD_RS;
|
CMP_RD_RS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MOV Rd, Rs
|
||||||
|
static INSN_REGPARM void thumb46_0(u32 opcode)
|
||||||
|
{
|
||||||
|
reg[opcode&7].I = reg[((opcode>>3)&7)].I;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
// MOV Rd, Hs
|
// MOV Rd, Hs
|
||||||
static INSN_REGPARM void thumb46_1(u32 opcode)
|
static INSN_REGPARM void thumb46_1(u32 opcode)
|
||||||
{
|
{
|
||||||
reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
|
reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MOV Hd, Rs
|
// MOV Hd, Rs
|
||||||
@ -1466,16 +1474,14 @@ static INSN_REGPARM void thumb47(u32 opcode)
|
|||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC)
|
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
|
||||||
+ codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
|
|
||||||
} else {
|
} else {
|
||||||
armState = true;
|
armState = true;
|
||||||
reg[15].I &= 0xFFFFFFFC;
|
reg[15].I &= 0xFFFFFFFC;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 4;
|
reg[15].I += 4;
|
||||||
ARM_PREFETCH;
|
ARM_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq32(armNextPC)
|
clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3;
|
||||||
+ codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1569,7 +1575,7 @@ static INSN_REGPARM void thumb5E(u32 opcode)
|
|||||||
if (busPrefetchCount == 0)
|
if (busPrefetchCount == 0)
|
||||||
busPrefetch = busPrefetchEnable;
|
busPrefetch = busPrefetchEnable;
|
||||||
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
|
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
|
||||||
reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
|
reg[opcode&7].I = (u32)CPUReadHalfWordSigned(address);
|
||||||
clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
|
clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1662,6 +1668,7 @@ static INSN_REGPARM void thumbA0(u32 opcode)
|
|||||||
{
|
{
|
||||||
u8 regist = (opcode >> 8) & 7;
|
u8 regist = (opcode >> 8) & 7;
|
||||||
reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
|
reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
|
||||||
|
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD R0~R7, SP, Imm
|
// ADD R0~R7, SP, Imm
|
||||||
@ -1669,6 +1676,7 @@ static INSN_REGPARM void thumbA8(u32 opcode)
|
|||||||
{
|
{
|
||||||
u8 regist = (opcode >> 8) & 7;
|
u8 regist = (opcode >> 8) & 7;
|
||||||
reg[regist].I = reg[13].I + ((opcode&255)<<2);
|
reg[regist].I = reg[13].I + ((opcode&255)<<2);
|
||||||
|
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD SP, Imm
|
// ADD SP, Imm
|
||||||
@ -1678,6 +1686,7 @@ static INSN_REGPARM void thumbB0(u32 opcode)
|
|||||||
if(opcode & 0x80)
|
if(opcode & 0x80)
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
reg[13].I += offset;
|
reg[13].I += offset;
|
||||||
|
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push and pop ///////////////////////////////////////////////////////////
|
// Push and pop ///////////////////////////////////////////////////////////
|
||||||
@ -1875,13 +1884,13 @@ static INSN_REGPARM void thumbC8(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD0(u32 opcode)
|
static INSN_REGPARM void thumbD0(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(Z_FLAG) {
|
if(Z_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1890,13 +1899,13 @@ static INSN_REGPARM void thumbD0(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD1(u32 opcode)
|
static INSN_REGPARM void thumbD1(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!Z_FLAG) {
|
if(!Z_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1905,13 +1914,13 @@ static INSN_REGPARM void thumbD1(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD2(u32 opcode)
|
static INSN_REGPARM void thumbD2(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(C_FLAG) {
|
if(C_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1920,13 +1929,13 @@ static INSN_REGPARM void thumbD2(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD3(u32 opcode)
|
static INSN_REGPARM void thumbD3(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!C_FLAG) {
|
if(!C_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1935,13 +1944,13 @@ static INSN_REGPARM void thumbD3(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD4(u32 opcode)
|
static INSN_REGPARM void thumbD4(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(N_FLAG) {
|
if(N_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1950,13 +1959,13 @@ static INSN_REGPARM void thumbD4(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD5(u32 opcode)
|
static INSN_REGPARM void thumbD5(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!N_FLAG) {
|
if(!N_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1965,13 +1974,13 @@ static INSN_REGPARM void thumbD5(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD6(u32 opcode)
|
static INSN_REGPARM void thumbD6(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(V_FLAG) {
|
if(V_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1980,13 +1989,13 @@ static INSN_REGPARM void thumbD6(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD7(u32 opcode)
|
static INSN_REGPARM void thumbD7(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!V_FLAG) {
|
if(!V_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1995,13 +2004,13 @@ static INSN_REGPARM void thumbD7(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD8(u32 opcode)
|
static INSN_REGPARM void thumbD8(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(C_FLAG && !Z_FLAG) {
|
if(C_FLAG && !Z_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2010,13 +2019,13 @@ static INSN_REGPARM void thumbD8(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbD9(u32 opcode)
|
static INSN_REGPARM void thumbD9(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!C_FLAG || Z_FLAG) {
|
if(!C_FLAG || Z_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2025,13 +2034,13 @@ static INSN_REGPARM void thumbD9(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbDA(u32 opcode)
|
static INSN_REGPARM void thumbDA(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(N_FLAG == V_FLAG) {
|
if(N_FLAG == V_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2040,13 +2049,13 @@ static INSN_REGPARM void thumbDA(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbDB(u32 opcode)
|
static INSN_REGPARM void thumbDB(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(N_FLAG != V_FLAG) {
|
if(N_FLAG != V_FLAG) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2055,13 +2064,13 @@ static INSN_REGPARM void thumbDB(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbDC(u32 opcode)
|
static INSN_REGPARM void thumbDC(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||||
if(!Z_FLAG && (N_FLAG == V_FLAG)) {
|
if(!Z_FLAG && (N_FLAG == V_FLAG)) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2070,13 +2079,13 @@ static INSN_REGPARM void thumbDC(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbDD(u32 opcode)
|
static INSN_REGPARM void thumbDD(u32 opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
UPDATE_OLDREG;
|
||||||
|
clockTicks = codeTicksAccessSeq16(armNextPC);
|
||||||
if(Z_FLAG || (N_FLAG != V_FLAG)) {
|
if(Z_FLAG || (N_FLAG != V_FLAG)) {
|
||||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||||
codeTicksAccess16(armNextPC)+3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2087,8 +2096,8 @@ static INSN_REGPARM void thumbDD(u32 opcode)
|
|||||||
static INSN_REGPARM void thumbDF(u32 opcode)
|
static INSN_REGPARM void thumbDF(u32 opcode)
|
||||||
{
|
{
|
||||||
u32 address = 0;
|
u32 address = 0;
|
||||||
clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) +
|
//clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3;
|
||||||
codeTicksAccess16(address)+3;
|
clockTicks = 3;
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
CPUSoftwareInterrupt(opcode & 0xFF);
|
CPUSoftwareInterrupt(opcode & 0xFF);
|
||||||
}
|
}
|
||||||
@ -2103,8 +2112,7 @@ static INSN_REGPARM void thumbE0(u32 opcode)
|
|||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3;
|
||||||
codeTicksAccess16(armNextPC) + 3;
|
|
||||||
busPrefetchCount=0;
|
busPrefetchCount=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2134,8 +2142,7 @@ static INSN_REGPARM void thumbF8(u32 opcode)
|
|||||||
reg[15].I += 2;
|
reg[15].I += 2;
|
||||||
reg[14].I = temp|1;
|
reg[14].I = temp|1;
|
||||||
THUMB_PREFETCH;
|
THUMB_PREFETCH;
|
||||||
clockTicks = codeTicksAccessSeq16(armNextPC) +
|
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
|
||||||
codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3;
|
|
||||||
busPrefetchCount = 0;
|
busPrefetchCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2184,7 +2191,7 @@ static insnfunc_t thumbInsnTable[1024] = {
|
|||||||
thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3, // 40
|
thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3, // 40
|
||||||
thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
|
thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
|
||||||
thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
|
thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
|
||||||
thumbUI,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
|
thumb46_0,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
|
||||||
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, // 48
|
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, // 48
|
||||||
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
|
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
|
||||||
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
|
thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
|
||||||
|
@ -78,6 +78,7 @@ extern char oldbuffer[10];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool CPUReadGSASnapshot(const char *);
|
extern bool CPUReadGSASnapshot(const char *);
|
||||||
|
extern bool CPUReadGSASPSnapshot(const char *);
|
||||||
extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
|
extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
|
||||||
extern bool CPUWriteBatteryFile(const char *);
|
extern bool CPUWriteBatteryFile(const char *);
|
||||||
extern bool CPUReadBatteryFile(const char *);
|
extern bool CPUReadBatteryFile(const char *);
|
||||||
@ -89,9 +90,14 @@ extern void CPUCleanUp();
|
|||||||
extern void CPUUpdateRender();
|
extern void CPUUpdateRender();
|
||||||
extern void CPUUpdateRenderBuffers(bool);
|
extern void CPUUpdateRenderBuffers(bool);
|
||||||
extern bool CPUReadMemState(char *, int);
|
extern bool CPUReadMemState(char *, int);
|
||||||
extern bool CPUReadState(const char *);
|
|
||||||
extern bool CPUWriteMemState(char *, int);
|
extern bool CPUWriteMemState(char *, int);
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
extern bool CPUReadState(const u8*, unsigned);
|
||||||
|
extern unsigned int CPUWriteState(u8 *data, unsigned int size);
|
||||||
|
#else
|
||||||
|
extern bool CPUReadState(const char *);
|
||||||
extern bool CPUWriteState(const char *);
|
extern bool CPUWriteState(const char *);
|
||||||
|
#endif
|
||||||
extern int CPULoadRom(const char *);
|
extern int CPULoadRom(const char *);
|
||||||
extern void doMirroring(bool);
|
extern void doMirroring(bool);
|
||||||
extern void CPUUpdateRegister(u32, u16);
|
extern void CPUUpdateRegister(u32, u16);
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
|
|
||||||
//#define SPRITE_DEBUG
|
//#define SPRITE_DEBUG
|
||||||
|
|
||||||
|
#ifdef TILED_RENDERING
|
||||||
|
extern void gfxDrawTextScreen(u16, u16, u16, u32 *);
|
||||||
|
#else
|
||||||
static void gfxDrawTextScreen(u16, u16, u16, u32 *);
|
static void gfxDrawTextScreen(u16, u16, u16, u32 *);
|
||||||
|
#endif
|
||||||
static void gfxDrawRotScreen(u16,
|
static void gfxDrawRotScreen(u16,
|
||||||
u16, u16,
|
u16, u16,
|
||||||
u16, u16,
|
u16, u16,
|
||||||
@ -98,6 +102,7 @@ static inline void gfxClearArray(u32 *array)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TILED_RENDERING
|
||||||
static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
|
static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
|
||||||
u32 *line)
|
u32 *line)
|
||||||
{
|
{
|
||||||
@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void gfxDrawRotScreen(u16 control,
|
static inline void gfxDrawRotScreen(u16 control,
|
||||||
u16 x_l, u16 x_h,
|
u16 x_l, u16 x_h,
|
||||||
|
187
source/vba/gba/GBALink.h
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#ifndef GBA_GBALINK_H
|
||||||
|
#define GBA_GBALINK_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// register definitions; these are always present
|
||||||
|
|
||||||
|
#define UNSUPPORTED -1
|
||||||
|
#define MULTIPLAYER 0
|
||||||
|
#define NORMAL8 1
|
||||||
|
#define NORMAL32 2
|
||||||
|
#define UART 3
|
||||||
|
#define JOYBUS 4
|
||||||
|
#define GP 5
|
||||||
|
|
||||||
|
#define RFU_INIT 0
|
||||||
|
#define RFU_COMM 1
|
||||||
|
#define RFU_SEND 2
|
||||||
|
#define RFU_RECV 3
|
||||||
|
|
||||||
|
#define COMM_SIODATA32_L 0x120
|
||||||
|
#define COMM_SIODATA32_H 0x122
|
||||||
|
#define COMM_SIOCNT 0x128
|
||||||
|
#define COMM_SIODATA8 0x12a
|
||||||
|
#define COMM_SIOMLT_SEND 0x12a
|
||||||
|
#define COMM_SIOMULTI0 0x120
|
||||||
|
#define COMM_SIOMULTI1 0x122
|
||||||
|
#define COMM_SIOMULTI2 0x124
|
||||||
|
#define COMM_SIOMULTI3 0x126
|
||||||
|
#define COMM_RCNT 0x134
|
||||||
|
#define COMM_JOYCNT 0x140
|
||||||
|
#define COMM_JOY_RECV_L 0x150
|
||||||
|
#define COMM_JOY_RECV_H 0x152
|
||||||
|
#define COMM_JOY_TRANS_L 0x154
|
||||||
|
#define COMM_JOY_TRANS_H 0x156
|
||||||
|
#define COMM_JOYSTAT 0x158
|
||||||
|
|
||||||
|
#define JOYSTAT_RECV 2
|
||||||
|
#define JOYSTAT_SEND 8
|
||||||
|
|
||||||
|
#define JOYCNT_RESET 1
|
||||||
|
#define JOYCNT_RECV_COMPLETE 2
|
||||||
|
#define JOYCNT_SEND_COMPLETE 4
|
||||||
|
#define JOYCNT_INT_ENABLE 0x40
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
JOY_CMD_RESET = 0xff,
|
||||||
|
JOY_CMD_STATUS = 0x00,
|
||||||
|
JOY_CMD_READ = 0x14,
|
||||||
|
JOY_CMD_WRITE = 0x15
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char *MakeInstanceFilename(const char *Input);
|
||||||
|
|
||||||
|
#ifndef NO_LINK
|
||||||
|
// Link implementation
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
#include <SFML/Network.hpp>
|
||||||
|
|
||||||
|
class ServerInfoDisplay
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void ShowServerIP(const sf::IPAddress& addr) = 0;
|
||||||
|
virtual void ShowConnect(const int player) = 0;
|
||||||
|
virtual void Ping() = 0;
|
||||||
|
virtual void Connected() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u16 linkdata[5];
|
||||||
|
u16 linkcmd;
|
||||||
|
u16 numtransfers;
|
||||||
|
int lastlinktime;
|
||||||
|
u8 numgbas;
|
||||||
|
u8 trgbas;
|
||||||
|
u8 linkflags;
|
||||||
|
int rfu_q[4];
|
||||||
|
u8 rfu_request[4];
|
||||||
|
int rfu_linktime[4];
|
||||||
|
u32 rfu_bdata[4][7];
|
||||||
|
u32 rfu_data[4][32];
|
||||||
|
} LINKDATA;
|
||||||
|
|
||||||
|
class lserver{
|
||||||
|
int numbytes;
|
||||||
|
sf::Selector<sf::SocketTCP> fdset;
|
||||||
|
//timeval udptimeout;
|
||||||
|
char inbuffer[256], outbuffer[256];
|
||||||
|
s32 *intinbuffer;
|
||||||
|
u16 *u16inbuffer;
|
||||||
|
s32 *intoutbuffer;
|
||||||
|
u16 *u16outbuffer;
|
||||||
|
int counter;
|
||||||
|
int done;
|
||||||
|
public:
|
||||||
|
int howmanytimes;
|
||||||
|
sf::SocketTCP tcpsocket[4];
|
||||||
|
sf::IPAddress udpaddr[4];
|
||||||
|
lserver(void);
|
||||||
|
bool Init(ServerInfoDisplay *);
|
||||||
|
void Send(void);
|
||||||
|
void Recv(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClientInfoDisplay {
|
||||||
|
public:
|
||||||
|
virtual void ConnectStart(const sf::IPAddress& addr) = 0;
|
||||||
|
virtual void Ping() = 0;
|
||||||
|
virtual void ShowConnect(const int player, const int togo) = 0;
|
||||||
|
virtual void Connected() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class lclient{
|
||||||
|
sf::Selector<sf::SocketTCP> fdset;
|
||||||
|
char inbuffer[256], outbuffer[256];
|
||||||
|
s32 *intinbuffer;
|
||||||
|
u16 *u16inbuffer;
|
||||||
|
s32 *intoutbuffer;
|
||||||
|
u16 *u16outbuffer;
|
||||||
|
int numbytes;
|
||||||
|
public:
|
||||||
|
sf::IPAddress serveraddr;
|
||||||
|
unsigned short serverport;
|
||||||
|
sf::SocketTCP noblock;
|
||||||
|
int numtransfers;
|
||||||
|
lclient(void);
|
||||||
|
bool Init(sf::IPAddress, ClientInfoDisplay *);
|
||||||
|
void Send(void);
|
||||||
|
void Recv(void);
|
||||||
|
void CheckConn(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sf::SocketTCP tcpsocket;
|
||||||
|
//sf::SocketUDP udpsocket;
|
||||||
|
int numslaves;
|
||||||
|
sf::Thread *thread;
|
||||||
|
int type;
|
||||||
|
bool server;
|
||||||
|
bool terminate;
|
||||||
|
bool connected;
|
||||||
|
bool speed;
|
||||||
|
bool active;
|
||||||
|
} LANLINKDATA;
|
||||||
|
|
||||||
|
extern bool gba_joybus_enabled;
|
||||||
|
extern bool gba_link_enabled;
|
||||||
|
|
||||||
|
extern sf::IPAddress joybusHostAddr;
|
||||||
|
extern void JoyBusConnect();
|
||||||
|
extern void JoyBusShutdown();
|
||||||
|
extern void JoyBusUpdate(int ticks);
|
||||||
|
|
||||||
|
extern bool InitLink();
|
||||||
|
extern void CloseLink();
|
||||||
|
extern void StartLink(u16);
|
||||||
|
extern void StartGPLink(u16);
|
||||||
|
extern void LinkUpdate(int);
|
||||||
|
extern void CleanLocalLink();
|
||||||
|
extern LANLINKDATA lanlink;
|
||||||
|
extern int vbaid;
|
||||||
|
extern bool rfu_enabled;
|
||||||
|
extern int linktimeout;
|
||||||
|
extern lclient lc;
|
||||||
|
extern lserver ls;
|
||||||
|
extern int linkid;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// stubs to keep #ifdef's out of mainline
|
||||||
|
const bool gba_joybus_enabled = false;
|
||||||
|
const bool gba_link_enabled = false;
|
||||||
|
|
||||||
|
inline void JoyBusConnect() { }
|
||||||
|
inline void JoyBusShutdown() { }
|
||||||
|
inline void JoyBusUpdate(int) { }
|
||||||
|
|
||||||
|
inline bool InitLink() { return true; }
|
||||||
|
inline void CloseLink() { }
|
||||||
|
inline void StartLink(u16) { }
|
||||||
|
inline void StartGPLink(u16) { }
|
||||||
|
inline void LinkUpdate(int) { }
|
||||||
|
inline void CleanLocalLink() { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GBA_GBALINK_H */
|
@ -5,8 +5,11 @@ extern int armExecute();
|
|||||||
extern int thumbExecute();
|
extern int thumbExecute();
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
#ifndef __APPLE__
|
||||||
|
# define INSN_REGPARM __attribute__((regparm(1)))
|
||||||
|
#else
|
||||||
# define INSN_REGPARM /*nothing*/
|
# define INSN_REGPARM /*nothing*/
|
||||||
//# define INSN_REGPARM __attribute__((regparm(1)))
|
#endif
|
||||||
# define LIKELY(x) __builtin_expect(!!(x),1)
|
# define LIKELY(x) __builtin_expect(!!(x),1)
|
||||||
# define UNLIKELY(x) __builtin_expect(!!(x),0)
|
# define UNLIKELY(x) __builtin_expect(!!(x),0)
|
||||||
#else
|
#else
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
#include "agbprint.h"
|
#include "agbprint.h"
|
||||||
#include "vmmem.h" // Nintendo GC Virtual Memory
|
#include "GBAcpu.h"
|
||||||
|
#include "GBALink.h"
|
||||||
|
|
||||||
extern const u32 objTilesAddress[3];
|
extern const u32 objTilesAddress[3];
|
||||||
|
|
||||||
@ -33,102 +34,32 @@ extern bool timer3On;
|
|||||||
extern int timer3Ticks;
|
extern int timer3Ticks;
|
||||||
extern int timer3ClockReload;
|
extern int timer3ClockReload;
|
||||||
extern int cpuTotalTicks;
|
extern int cpuTotalTicks;
|
||||||
extern u32 RomIdCode;
|
|
||||||
|
|
||||||
#define gid(a,b,c) (a|(b<<8)|(c<<16))
|
#define CPUReadByteQuick(addr) \
|
||||||
#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]
|
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
|
||||||
|
|
||||||
#define CPUReadHalfWordQuickDef(addr) \
|
#define CPUReadHalfWordQuick(addr) \
|
||||||
READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
||||||
|
|
||||||
#define CPUReadMemoryQuickDef(addr) \
|
#define CPUReadMemoryQuick(addr) \
|
||||||
READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
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)
|
static inline u32 CPUReadMemory(u32 address)
|
||||||
{
|
{
|
||||||
#ifdef GBA_LOGGING
|
|
||||||
if(address & 3) {
|
|
||||||
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
|
||||||
log("Unaligned word read: %08x at %08x\n", address, armMode ?
|
|
||||||
armNextPC - 4 : armNextPC - 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u32 value;
|
u32 value;
|
||||||
|
u32 oldAddress = address;
|
||||||
|
|
||||||
|
if(address & 3) {
|
||||||
|
address &= ~0x03;
|
||||||
|
}
|
||||||
|
|
||||||
switch(address >> 24) {
|
switch(address >> 24) {
|
||||||
case 0x00:
|
case 0:
|
||||||
if(reg[15].I >> 24) {
|
if(reg[15].I >> 24) {
|
||||||
if(address < 0x4000) {
|
if(address < 0x4000) {
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
log("Illegal word read from bios: %08x at %08x\n", address, armMode ?
|
||||||
armNextPC - 4 : armNextPC - 2);
|
armNextPC - 4 : armNextPC - 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -139,24 +70,29 @@ static inline u32 CPUReadMemory(u32 address)
|
|||||||
} else
|
} else
|
||||||
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
|
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 2:
|
||||||
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
|
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 3:
|
||||||
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
|
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 4:
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
||||||
if(ioReadable[(address & 0x3fc) + 2])
|
if(ioReadable[(address & 0x3fc) + 2]) {
|
||||||
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
|
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
|
||||||
else
|
if ((address & 0x3fc) == COMM_JOY_RECV_L)
|
||||||
|
UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV);
|
||||||
|
} else {
|
||||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
|
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
|
||||||
} else goto unreadable;
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto unreadable;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 5:
|
||||||
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
|
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 6:
|
||||||
address = (address & 0x1fffc);
|
address = (address & 0x1fffc);
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
{
|
{
|
||||||
@ -167,78 +103,48 @@ static inline u32 CPUReadMemory(u32 address)
|
|||||||
address &= 0x17fff;
|
address &= 0x17fff;
|
||||||
value = READ32LE(((u32 *)&vram[address]));
|
value = READ32LE(((u32 *)&vram[address]));
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 7:
|
||||||
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
|
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 8:
|
||||||
// Must be cartridge ROM, reading other sensors doesn't allow 32-bit access.
|
case 9:
|
||||||
case 0x09:
|
case 10:
|
||||||
case 0x0A:
|
case 11:
|
||||||
case 0x0B:
|
case 12:
|
||||||
case 0x0C:
|
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
|
||||||
value = VMRead32( address & 0x1FFFFFC );
|
|
||||||
#else
|
|
||||||
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
|
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 0x0D:
|
case 13:
|
||||||
if(cpuEEPROMEnabled)
|
value = eepromRead(address);
|
||||||
// no need to swap this
|
break;
|
||||||
return eepromRead(address);
|
case 14:
|
||||||
goto unreadable;
|
case 15:
|
||||||
case 0x0E:
|
value = flashRead(address) * 0x01010101;
|
||||||
// Yoshi's Universal Gravitation (Topsy Turvy)
|
break;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(cpuFlashEnabled | cpuSramEnabled)
|
|
||||||
// no need to swap this
|
|
||||||
return flashRead(address);
|
|
||||||
// default
|
// default
|
||||||
default:
|
default:
|
||||||
unreadable:
|
unreadable:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
||||||
armNextPC - 4 : armNextPC - 2);
|
armNextPC - 4 : armNextPC - 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(cpuDmaHack) {
|
if(cpuDmaHack) {
|
||||||
value = cpuDmaLast;
|
value = cpuDmaLast;
|
||||||
} else {
|
} else {
|
||||||
if(armState) {
|
if(armState) {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
return CPUReadMemoryQuick(reg[15].I);
|
||||||
value = CPUReadMemoryQuick(reg[15].I);
|
|
||||||
#else
|
|
||||||
value = CPUReadMemoryQuickDef(reg[15].I);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
return CPUReadHalfWordQuick(reg[15].I) |
|
||||||
value = CPUReadHalfWordQuick(reg[15].I) |
|
|
||||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||||
#else
|
|
||||||
value = CPUReadHalfWordQuickDef(reg[15].I) |
|
|
||||||
CPUReadHalfWordQuickDef(reg[15].I) << 16;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address & 3) {
|
if(oldAddress & 3) {
|
||||||
#ifdef C_CORE
|
#ifdef C_CORE
|
||||||
int shift = (address & 3) << 3;
|
int shift = (oldAddress & 3) << 3;
|
||||||
value = (value >> shift) | (value << (32 - shift));
|
value = (value >> shift) | (value << (32 - shift));
|
||||||
#else
|
#else
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
@ -246,10 +152,10 @@ static inline u32 CPUReadMemory(u32 address)
|
|||||||
"shl $3 ,%%ecx;"
|
"shl $3 ,%%ecx;"
|
||||||
"ror %%cl, %0"
|
"ror %%cl, %0"
|
||||||
: "=r" (value)
|
: "=r" (value)
|
||||||
: "r" (value), "c" (address));
|
: "r" (value), "c" (oldAddress));
|
||||||
#else
|
#else
|
||||||
__asm {
|
__asm {
|
||||||
mov ecx, address;
|
mov ecx, oldAddress;
|
||||||
and ecx, 3;
|
and ecx, 3;
|
||||||
shl ecx, 3;
|
shl ecx, 3;
|
||||||
ror [dword ptr value], cl;
|
ror [dword ptr value], cl;
|
||||||
@ -257,6 +163,15 @@ static inline u32 CPUReadMemory(u32 address)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GBA_LOGGING
|
||||||
|
if(oldAddress & 3) {
|
||||||
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
|
log("Unaligned word read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
|
||||||
|
armNextPC - 4 : armNextPC - 2, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,24 +179,20 @@ extern u32 myROM[];
|
|||||||
|
|
||||||
static inline u32 CPUReadHalfWord(u32 address)
|
static inline u32 CPUReadHalfWord(u32 address)
|
||||||
{
|
{
|
||||||
#ifdef GBA_LOGGING
|
|
||||||
if(address & 1) {
|
|
||||||
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
|
||||||
log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
|
|
||||||
armNextPC - 4 : armNextPC - 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u32 value;
|
u32 value;
|
||||||
|
u32 oldAddress = address;
|
||||||
|
|
||||||
|
if(address & 1) {
|
||||||
|
address &= ~0x01;
|
||||||
|
}
|
||||||
|
|
||||||
switch(address >> 24) {
|
switch(address >> 24) {
|
||||||
case 0x00:
|
case 0:
|
||||||
if (reg[15].I >> 24) {
|
if (reg[15].I >> 24) {
|
||||||
if(address < 0x4000) {
|
if(address < 0x4000) {
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
log("Illegal halfword read from bios: %08x at %08x\n", oldAddress, armMode ?
|
||||||
armNextPC - 4 : armNextPC - 2);
|
armNextPC - 4 : armNextPC - 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -290,13 +201,13 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||||||
} else
|
} else
|
||||||
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
|
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 2:
|
||||||
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
|
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 3:
|
||||||
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
|
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 4:
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3fe])
|
if((address < 0x4000400) && ioReadable[address & 0x3fe])
|
||||||
{
|
{
|
||||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
|
value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
|
||||||
@ -315,12 +226,16 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||||||
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
|
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if((address < 0x4000400) && ioReadable[address & 0x3fc])
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
else goto unreadable;
|
else goto unreadable;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 5:
|
||||||
value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
|
value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 6:
|
||||||
address = (address & 0x1fffe);
|
address = (address & 0x1fffe);
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
{
|
{
|
||||||
@ -331,105 +246,83 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||||||
address &= 0x17fff;
|
address &= 0x17fff;
|
||||||
value = READ16LE(((u16 *)&vram[address]));
|
value = READ16LE(((u16 *)&vram[address]));
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 7:
|
||||||
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
|
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 8:
|
||||||
// Use existing case statement and faster test for potential speed improvement
|
case 9:
|
||||||
// This is possibly the GPIO port that controls the real time clock,
|
case 10:
|
||||||
// WarioWare Twisted! tilt sensors, rumble, and solar sensors.
|
case 11:
|
||||||
if(address >= 0x80000c4 && address <= 0x80000c8) {
|
case 12:
|
||||||
// this function still works if there is no real time clock
|
if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
|
||||||
// and does a normal memory read in that case.
|
value = rtcRead(address);
|
||||||
value = rtcRead(address & 0xFFFFFFE);
|
else
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x09:
|
|
||||||
case 0x0A:
|
|
||||||
case 0x0B:
|
|
||||||
case 0x0C:
|
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
|
||||||
value = VMRead16( address & 0x1FFFFFE );
|
|
||||||
#else
|
|
||||||
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
|
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 0x0D:
|
case 13:
|
||||||
if(cpuEEPROMEnabled)
|
value = eepromRead(address);
|
||||||
// no need to swap this
|
break;
|
||||||
return eepromRead(address);
|
case 14:
|
||||||
goto unreadable;
|
case 15:
|
||||||
case 0x0E:
|
value = flashRead(address) * 0x0101;
|
||||||
// Yoshi's Universal Gravitation (Topsy Turvy)
|
break;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(cpuFlashEnabled | cpuSramEnabled)
|
|
||||||
// no need to swap this
|
|
||||||
return flashRead(address);
|
|
||||||
// default
|
// default
|
||||||
default:
|
default:
|
||||||
unreadable:
|
unreadable:
|
||||||
#ifdef GBA_LOGGING
|
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
|
||||||
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
|
||||||
armNextPC - 4 : armNextPC - 2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(cpuDmaHack) {
|
if(cpuDmaHack) {
|
||||||
value = cpuDmaLast & 0xFFFF;
|
value = cpuDmaLast & 0xFFFF;
|
||||||
} else {
|
} else {
|
||||||
if(armState) {
|
if(armState) {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
|
||||||
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
|
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
|
||||||
#else
|
|
||||||
value = CPUReadHalfWordQuickDef(reg[15].I + (address & 2));
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
|
||||||
value = CPUReadHalfWordQuick(reg[15].I);
|
value = CPUReadHalfWordQuick(reg[15].I);
|
||||||
#else
|
}
|
||||||
value = CPUReadHalfWordQuickDef(reg[15].I);
|
}
|
||||||
|
#ifdef GBA_LOGGING
|
||||||
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
|
log("Illegal halfword read: %08x at %08x (%08x)\n", oldAddress, reg[15].I, value);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
return value;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address & 1) {
|
if(oldAddress & 1) {
|
||||||
value = (value >> 8) | (value << 24);
|
value = (value >> 8) | (value << 24);
|
||||||
|
#ifdef GBA_LOGGING
|
||||||
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
|
log("Unaligned halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
|
||||||
|
armNextPC - 4 : armNextPC - 2, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u16 CPUReadHalfWordSigned(u32 address)
|
static inline s16 CPUReadHalfWordSigned(u32 address)
|
||||||
{
|
{
|
||||||
u16 value = CPUReadHalfWord(address);
|
s32 value = (s32)CPUReadHalfWord(address);
|
||||||
if((address & 1))
|
if((address & 1))
|
||||||
value = (s8)value;
|
{
|
||||||
return value;
|
#ifdef GBA_LOGGING
|
||||||
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
|
log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", address, armMode ?
|
||||||
|
armNextPC - 4 : armNextPC - 2, value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return (s16)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 CPUReadByte(u32 address)
|
static inline u8 CPUReadByte(u32 address)
|
||||||
{
|
{
|
||||||
switch(address >> 24) {
|
switch(address >> 24) {
|
||||||
case 0x00:
|
case 0:
|
||||||
if (reg[15].I >> 24) {
|
if (reg[15].I >> 24) {
|
||||||
if(address < 0x4000) {
|
if(address < 0x4000) {
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
log("Illegal byte read from bios: %08x at %08x\n", address, armMode ?
|
||||||
armNextPC - 4 : armNextPC - 2);
|
armNextPC - 4 : armNextPC - 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -437,60 +330,53 @@ static inline u8 CPUReadByte(u32 address)
|
|||||||
} else goto unreadable;
|
} else goto unreadable;
|
||||||
}
|
}
|
||||||
return bios[address & 0x3FFF];
|
return bios[address & 0x3FFF];
|
||||||
case 0x02:
|
case 2:
|
||||||
return workRAM[address & 0x3FFFF];
|
return workRAM[address & 0x3FFFF];
|
||||||
case 0x03:
|
case 3:
|
||||||
return internalRAM[address & 0x7fff];
|
return internalRAM[address & 0x7fff];
|
||||||
case 0x04:
|
case 4:
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3ff])
|
if((address < 0x4000400) && ioReadable[address & 0x3ff])
|
||||||
return ioMem[address & 0x3ff];
|
return ioMem[address & 0x3ff];
|
||||||
else goto unreadable;
|
else goto unreadable;
|
||||||
case 0x05:
|
case 5:
|
||||||
return paletteRAM[address & 0x3ff];
|
return paletteRAM[address & 0x3ff];
|
||||||
case 0x06:
|
case 6:
|
||||||
address = (address & 0x1ffff);
|
address = (address & 0x1ffff);
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
return 0;
|
return 0;
|
||||||
if ((address & 0x18000) == 0x18000)
|
if ((address & 0x18000) == 0x18000)
|
||||||
address &= 0x17fff;
|
address &= 0x17fff;
|
||||||
return vram[address];
|
return vram[address];
|
||||||
case 0x07:
|
case 7:
|
||||||
return oam[address & 0x3ff];
|
return oam[address & 0x3ff];
|
||||||
case 0x08:
|
case 8:
|
||||||
// the real time clock doesn't support byte reads, so don't bother checking for it.
|
case 9:
|
||||||
case 0x09:
|
case 10:
|
||||||
case 0x0A:
|
case 11:
|
||||||
case 0x0B:
|
case 12:
|
||||||
case 0x0C:
|
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
|
||||||
return VMRead8( address & 0x1FFFFFF );
|
|
||||||
#else
|
|
||||||
return rom[address & 0x1FFFFFF];
|
return rom[address & 0x1FFFFFF];
|
||||||
#endif
|
case 13:
|
||||||
case 0x0D:
|
|
||||||
if(cpuEEPROMEnabled)
|
|
||||||
return eepromRead(address);
|
return eepromRead(address);
|
||||||
goto unreadable;
|
case 14:
|
||||||
case 0x0E:
|
case 15:
|
||||||
// Yoshi's Universal Gravitation (Topsy Turvy)
|
{
|
||||||
// Koro Koro
|
if (cpuEEPROMSensorEnabled) {
|
||||||
if(cpuEEPROMSensorEnabled) {
|
switch (address & 0x00008f00) {
|
||||||
switch(address & 0x00008f00) {
|
|
||||||
case 0x8200:
|
case 0x8200:
|
||||||
return systemGetSensorX() & 255;
|
return systemGetSensorX() & 255;
|
||||||
case 0x8300:
|
case 0x8300:
|
||||||
return (systemGetSensorX() >> 8)|0x80;
|
return (systemGetSensorX() >> 8) | 0x80;
|
||||||
case 0x8400:
|
case 0x8400:
|
||||||
return systemGetSensorY() & 255;
|
return systemGetSensorY() & 255;
|
||||||
case 0x8500:
|
case 0x8500:
|
||||||
return systemGetSensorY() >> 8;
|
return systemGetSensorY() >> 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cpuSramEnabled | cpuFlashEnabled)
|
|
||||||
return flashRead(address);
|
return flashRead(address);
|
||||||
|
}
|
||||||
// default
|
// default
|
||||||
default:
|
default:
|
||||||
unreadable:
|
unreadable:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
||||||
@ -501,20 +387,11 @@ static inline u8 CPUReadByte(u32 address)
|
|||||||
return cpuDmaLast & 0xFF;
|
return cpuDmaLast & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
if(armState) {
|
if(armState) {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
return CPUReadByteQuick(reg[15].I + (address & 3));
|
||||||
return CPUReadByteQuick(reg[15].I+(address & 3));
|
|
||||||
#else
|
|
||||||
return CPUReadByteQuickDef(reg[15].I+(address & 3));
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_VM // Nintendo GC Virtual Memory
|
return CPUReadByteQuick(reg[15].I + (address & 1));
|
||||||
return CPUReadByteQuick(reg[15].I+(address & 1));
|
|
||||||
#else
|
|
||||||
return CPUReadByteQuickDef(reg[15].I+(address & 1));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,6 +409,8 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
address &= 0xFFFFFFFC;
|
||||||
|
|
||||||
switch(address >> 24) {
|
switch(address >> 24) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
#ifdef BKPT_SUPPORT
|
#ifdef BKPT_SUPPORT
|
||||||
@ -564,7 +443,6 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||||||
value);
|
value);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE)
|
|
||||||
WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
|
WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
@ -598,13 +476,14 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||||||
}
|
}
|
||||||
goto unwritable;
|
goto unwritable;
|
||||||
case 0x0E:
|
case 0x0E:
|
||||||
if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
|
case 0x0F:
|
||||||
|
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
|
||||||
(*cpuSaveGameFunc)(address, (u8)value);
|
(*cpuSaveGameFunc)(address, (u8)value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// default
|
// default
|
||||||
default:
|
default:
|
||||||
unwritable:
|
unwritable:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
||||||
log("Illegal word write: %08x to %08x from %08x\n",
|
log("Illegal word write: %08x to %08x from %08x\n",
|
||||||
@ -630,6 +509,8 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
address &= 0xFFFFFFFE;
|
||||||
|
|
||||||
switch(address >> 24) {
|
switch(address >> 24) {
|
||||||
case 2:
|
case 2:
|
||||||
#ifdef BKPT_SUPPORT
|
#ifdef BKPT_SUPPORT
|
||||||
@ -661,7 +542,6 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||||||
value);
|
value);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE)
|
|
||||||
WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value);
|
WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
@ -701,13 +581,14 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||||||
}
|
}
|
||||||
goto unwritable;
|
goto unwritable;
|
||||||
case 14:
|
case 14:
|
||||||
if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
|
case 15:
|
||||||
|
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
|
||||||
(*cpuSaveGameFunc)(address, (u8)value);
|
(*cpuSaveGameFunc)(address, (u8)value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto unwritable;
|
goto unwritable;
|
||||||
default:
|
default:
|
||||||
unwritable:
|
unwritable:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
||||||
log("Illegal halfword write: %04x to %08x from %08x\n",
|
log("Illegal halfword write: %04x to %08x from %08x\n",
|
||||||
@ -837,7 +718,8 @@ static inline void CPUWriteByte(u32 address, u8 b)
|
|||||||
}
|
}
|
||||||
goto unwritable;
|
goto unwritable;
|
||||||
case 14:
|
case 14:
|
||||||
if (!(saveType == 5) && (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)) {
|
case 15:
|
||||||
|
if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) {
|
||||||
|
|
||||||
//if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {
|
//if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {
|
||||||
|
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
@ -15,18 +7,9 @@ void mode0RenderLine()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
int x = 232; //240 - 8
|
for(int x = 0; x < 240; x++) {
|
||||||
do{
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,54 +38,10 @@ void mode0RenderLine()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u32 x = 0; x < 240u; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
//--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) {
|
if(line0[x] < color) {
|
||||||
color = line0[x];
|
color = line0[x];
|
||||||
top = 0x01;
|
top = 0x01;
|
||||||
@ -117,49 +56,41 @@ void mode0RenderLine()
|
|||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((u8)(line3[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(line3[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = line3[x];
|
color = line3[x];
|
||||||
top = 0x08;
|
top = 0x08;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
//*/
|
|
||||||
|
|
||||||
if((top & 0x10) && (color & 0x00010000)) {
|
if((top & 0x10) && (color & 0x00010000)) {
|
||||||
// semi-transparent OBJ
|
// semi-transparent OBJ
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
u8 li0 = (u8)(line0[x]>>24);
|
if((u8)(line0[x]>>24) < (u8)(back >> 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];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}else if(r == li1){
|
}
|
||||||
|
|
||||||
|
if((u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if((u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -188,20 +119,9 @@ void mode0RenderLineNoWindow()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,39 +156,30 @@ void mode0RenderLineNoWindow()
|
|||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
u8 li1 = (u8)(line1[x]>>24);
|
if(line0[x] < color) {
|
||||||
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];
|
color = line0[x];
|
||||||
top = 0x01;
|
top = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r < (u8)(color >> 24)) {
|
if(line1[x] < (color & 0xFF000000)) {
|
||||||
if(r == li1){
|
|
||||||
color = line1[x];
|
color = line1[x];
|
||||||
top = 0x02;
|
top = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if(line2[x] < (color & 0xFF000000)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if(line3[x] < (color & 0xFF000000)) {
|
||||||
color = line3[x];
|
color = line3[x];
|
||||||
top = 0x08;
|
top = 0x08;
|
||||||
}else if(r == li4){
|
}
|
||||||
|
|
||||||
|
if(lineOBJ[x] < (color & 0xFF000000)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!(color & 0x00010000)) {
|
if(!(color & 0x00010000)) {
|
||||||
switch(effect) {
|
switch(effect) {
|
||||||
@ -279,30 +190,40 @@ void mode0RenderLineNoWindow()
|
|||||||
if(top & BLDMOD) {
|
if(top & BLDMOD) {
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
if(line0[x] < back) {
|
||||||
if((top != 0x01) && line0[x] < back) {
|
if(top != 0x01) {
|
||||||
back = line0[x];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}
|
}
|
||||||
if((top != 0x02) && line1[x] < (back & 0xFF000000)) {
|
}
|
||||||
|
|
||||||
|
if(line1[x] < (back & 0xFF000000)) {
|
||||||
|
if(top != 0x02) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x04) && line2[x] < (back & 0xFF000000)) {
|
if(line2[x] < (back & 0xFF000000)) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x08) && line3[x] < (back & 0xFF000000)) {
|
if(line3[x] < (back & 0xFF000000)) {
|
||||||
|
if(top != 0x08) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x10) && lineOBJ[x] < (back & 0xFF000000)) {
|
if(lineOBJ[x] < (back & 0xFF000000)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -326,43 +247,25 @@ void mode0RenderLineNoWindow()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
//--DCN
|
if(line0[x] < back) {
|
||||||
// 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];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}else if(r == li1){
|
}
|
||||||
|
|
||||||
|
if(line1[x] < (back & 0xFF000000)) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if(line2[x] < (back & 0xFF000000)) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if(line3[x] < (back & 0xFF000000)) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -391,20 +294,9 @@ void mode0RenderLineAll()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,31 +448,40 @@ void mode0RenderLineAll()
|
|||||||
if(top & BLDMOD) {
|
if(top & BLDMOD) {
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
||||||
if((mask & 1) && (top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
if(top != 0x01) {
|
||||||
back = line0[x];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 2) && (top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x02) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 8) && (top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x08) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
@ -16,20 +7,9 @@ void mode1RenderLine()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -60,64 +40,49 @@ void mode1RenderLine()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(u32 x = 0; x < 240u; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
u8 li1 = (u8)(line1[x]>>24);
|
if(line0[x] < color) {
|
||||||
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];
|
color = line0[x];
|
||||||
top = 0x01;
|
top = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r < (u8)(color >> 24)) {
|
if((u8)(line1[x]>>24) < (u8)(color >> 24)) {
|
||||||
if(r == li1){
|
|
||||||
color = line1[x];
|
color = line1[x];
|
||||||
top = 0x02;
|
top = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if((u8)(line2[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}else if(r == li4){
|
}
|
||||||
|
|
||||||
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if((top & 0x10) && (color & 0x00010000)) {
|
if((top & 0x10) && (color & 0x00010000)) {
|
||||||
// semi-transparent OBJ
|
// semi-transparent OBJ
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
u8 li0 = (u8)(line0[x]>>24);
|
if((u8)(line0[x]>>24) < (u8)(back >> 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];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}else if(r == li1){
|
}
|
||||||
|
|
||||||
|
if((u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -148,20 +113,9 @@ void mode1RenderLineNoWindow()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -193,37 +147,29 @@ void mode1RenderLineNoWindow()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
u8 li1 = (u8)(line1[x]>>24);
|
if(line0[x] < color) {
|
||||||
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];
|
color = line0[x];
|
||||||
top = 0x01;
|
top = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r < (u8)(color >> 24)) {
|
if((u8)(line1[x]>>24) < (u8)(color >> 24)) {
|
||||||
if(r == li1){
|
|
||||||
color = line1[x];
|
color = line1[x];
|
||||||
top = 0x02;
|
top = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if((u8)(line2[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}else if(r == li4){
|
}
|
||||||
|
|
||||||
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!(color & 0x00010000)) {
|
if(!(color & 0x00010000)) {
|
||||||
switch((BLDMOD >> 6) & 3) {
|
switch((BLDMOD >> 6) & 3) {
|
||||||
@ -234,26 +180,33 @@ void mode1RenderLineNoWindow()
|
|||||||
if(top & BLDMOD) {
|
if(top & BLDMOD) {
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
if((u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
||||||
if((top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
if(top != 0x01) {
|
||||||
back = line0[x];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x02) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -276,28 +229,20 @@ void mode1RenderLineNoWindow()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
u8 li0 = (u8)(line0[x]>>24);
|
if((u8)(line0[x]>>24) < (u8)(back >> 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];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}else if(r == li1){
|
}
|
||||||
|
|
||||||
|
if((u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}else if(r == li2){
|
}
|
||||||
|
|
||||||
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -328,20 +273,9 @@ void mode1RenderLineAll()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -399,7 +333,7 @@ void mode1RenderLineAll()
|
|||||||
u8 inWin1Mask = WININ >> 8;
|
u8 inWin1Mask = WININ >> 8;
|
||||||
u8 outMask = WINOUT & 0xFF;
|
u8 outMask = WINOUT & 0xFF;
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
u8 mask = outMask;
|
u8 mask = outMask;
|
||||||
@ -419,23 +353,22 @@ void mode1RenderLineAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// At the very least, move the inexpensive 'mask' operation up front
|
if(line0[x] < color && (mask & 1)) {
|
||||||
if((mask & 1) && line0[x] < backdrop) {
|
|
||||||
color = line0[x];
|
color = line0[x];
|
||||||
top = 0x01;
|
top = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(line1[x]>>24) < (u8)(color >> 24) && (mask & 2)) {
|
||||||
color = line1[x];
|
color = line1[x];
|
||||||
top = 0x02;
|
top = 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(line2[x]>>24) < (u8)(color >> 24) && (mask & 4)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
@ -445,7 +378,7 @@ void mode1RenderLineAll()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(backdrop >> 24)) {
|
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line0[x];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}
|
}
|
||||||
@ -487,25 +420,33 @@ void mode1RenderLineAll()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 1) && (top != 0x01) && (u8)(line0[x]>>24) < (u8)(backdrop >> 24)) {
|
if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x01) {
|
||||||
back = line0[x];
|
back = line0[x];
|
||||||
top2 = 0x01;
|
top2 = 0x01;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 2) && (top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 2) && (u8)(line1[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x02) {
|
||||||
back = line1[x];
|
back = line1[x];
|
||||||
top2 = 0x02;
|
top2 = 0x02;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 4) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
@ -15,20 +7,9 @@ void mode2RenderLine()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -62,51 +43,40 @@ void mode2RenderLine()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
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((u8)(line2[x]>>24) < (u8)(color >> 24)) {
|
||||||
|
|
||||||
if(li4 < r){
|
|
||||||
r = (li4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r < (u8)(color >> 24)) {
|
|
||||||
if(r == li2){
|
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if((u8)(line3[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = line3[x];
|
color = line3[x];
|
||||||
top = 0x08;
|
top = 0x08;
|
||||||
}else if(r == li4){
|
}
|
||||||
|
|
||||||
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if((top & 0x10) && (color & 0x00010000)) {
|
if((top & 0x10) && (color & 0x00010000)) {
|
||||||
// semi-transparent OBJ
|
// semi-transparent OBJ
|
||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
u8 li2 = (u8)(line2[x]>>24);
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
u8 li3 = (u8)(line3[x]>>24);
|
|
||||||
u8 r = (li3 < li2) ? (li3) : (li2);
|
|
||||||
|
|
||||||
if(r < (u8)(back >> 24)) {
|
|
||||||
if(r == li2){
|
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if((u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -138,20 +108,9 @@ void mode2RenderLineNoWindow()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -185,32 +144,25 @@ void mode2RenderLineNoWindow()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
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((u8)(line2[x]>>24) < (u8)(color >> 24)) {
|
||||||
|
|
||||||
if(li4 < r){
|
|
||||||
r = (li4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r < (u8)(color >> 24)) {
|
|
||||||
if(r == li2){
|
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if((u8)(line3[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = line3[x];
|
color = line3[x];
|
||||||
top = 0x08;
|
top = 0x08;
|
||||||
}else if(r == li4){
|
}
|
||||||
|
|
||||||
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!(color & 0x00010000)) {
|
if(!(color & 0x00010000)) {
|
||||||
switch((BLDMOD >> 6) & 3) {
|
switch((BLDMOD >> 6) & 3) {
|
||||||
@ -222,20 +174,26 @@ void mode2RenderLineNoWindow()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x08) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -258,19 +216,15 @@ void mode2RenderLineNoWindow()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
u8 li2 = (u8)(line2[x]>>24);
|
if((u8)(line2[x]>>24) < (u8)(back >> 24)) {
|
||||||
u8 li3 = (u8)(line3[x]>>24);
|
|
||||||
u8 r = (li3 < li2) ? (li3) : (li2);
|
|
||||||
|
|
||||||
if(r < (u8)(back >> 24)) {
|
|
||||||
if(r == li2){
|
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}else if(r == li3){
|
}
|
||||||
|
|
||||||
|
if((u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -302,20 +256,9 @@ void mode2RenderLineAll()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -396,17 +339,17 @@ void mode2RenderLineAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 4) && line2[x] < color) {
|
if(line2[x] < color && (mask & 4)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(line3[x]>>24) < (u8)(color >> 24) && (mask & 8)) {
|
||||||
color = line3[x];
|
color = line3[x];
|
||||||
top = 0x08;
|
top = 0x08;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24) && (mask & 16)) {
|
||||||
color = lineOBJ[x];
|
color = lineOBJ[x];
|
||||||
top = 0x10;
|
top = 0x10;
|
||||||
}
|
}
|
||||||
@ -453,20 +396,26 @@ void mode2RenderLineAll()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && line2[x] < back) {
|
if((mask & 4) && line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 8) && (top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 8) && (u8)(line3[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x08) {
|
||||||
back = line3[x];
|
back = line3[x];
|
||||||
top2 = 0x08;
|
top2 = 0x08;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
@ -14,20 +7,9 @@ void mode3RenderLine()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -54,7 +36,7 @@ void mode3RenderLine()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
@ -73,7 +55,7 @@ void mode3RenderLine()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if(line2[x] < background) {
|
if(line2[x] < back) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
@ -107,20 +89,9 @@ void mode3RenderLineNoWindow()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -147,11 +118,11 @@ void mode3RenderLineNoWindow()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
if(line2[x] < background) {
|
if(line2[x] < color) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -171,15 +142,19 @@ void mode3RenderLineNoWindow()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if(top != 0x04 && (line2[x] < background) ) {
|
if(line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top != 0x10 && ((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -203,7 +178,7 @@ void mode3RenderLineNoWindow()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if(line2[x] < background) {
|
if(line2[x] < back) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
@ -237,20 +212,9 @@ void mode3RenderLineAll()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x80) {
|
if(DISPCNT & 0x80) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -304,7 +268,7 @@ void mode3RenderLineAll()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
u8 mask = outMask;
|
u8 mask = outMask;
|
||||||
@ -324,7 +288,7 @@ void mode3RenderLineAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 4) && line2[x] < background) {
|
if((mask & 4) && (line2[x] < color)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -339,7 +303,7 @@ void mode3RenderLineAll()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 4) && line2[x] < background) {
|
if((mask & 4) && line2[x] < back) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
@ -370,20 +334,25 @@ void mode3RenderLineAll()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && line2[x] < back) {
|
if((mask & 4) && line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
coeff[COLEV & 0x1F],
|
coeff[COLEV & 0x1F],
|
||||||
coeff[(COLEV >> 8) & 0x1F]);
|
coeff[(COLEV >> 8) & 0x1F]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
@ -14,20 +7,9 @@ void mode4RenderLine()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,11 +35,11 @@ void mode4RenderLine()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
if(line2[x] < backdrop) {
|
if(line2[x] < color) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -72,7 +54,7 @@ void mode4RenderLine()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if(line2[x] < backdrop) {
|
if(line2[x] < back) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
@ -106,20 +88,9 @@ void mode4RenderLineNoWindow()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -145,11 +116,11 @@ void mode4RenderLineNoWindow()
|
|||||||
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
if(line2[x] < backdrop) {
|
if(line2[x] < color) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -169,15 +140,19 @@ void mode4RenderLineNoWindow()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((top != 0x04) && line2[x] < backdrop) {
|
if(line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -235,20 +210,9 @@ void mode4RenderLineAll()
|
|||||||
u16 *palette = (u16 *)paletteRAM;
|
u16 *palette = (u16 *)paletteRAM;
|
||||||
|
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -301,7 +265,7 @@ void mode4RenderLineAll()
|
|||||||
u8 inWin1Mask = WININ >> 8;
|
u8 inWin1Mask = WININ >> 8;
|
||||||
u8 outMask = WINOUT & 0xFF;
|
u8 outMask = WINOUT & 0xFF;
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = backdrop;
|
u32 color = backdrop;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
u8 mask = outMask;
|
u8 mask = outMask;
|
||||||
@ -321,7 +285,7 @@ void mode4RenderLineAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 4) && (line2[x] < backdrop)) {
|
if((mask & 4) && (line2[x] < color)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -367,20 +331,25 @@ void mode4RenderLineAll()
|
|||||||
u32 back = backdrop;
|
u32 back = backdrop;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && (line2[x] < backdrop)) {
|
if((mask & 4) && line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
coeff[COLEV & 0x1F],
|
coeff[COLEV & 0x1F],
|
||||||
coeff[(COLEV >> 8) & 0x1F]);
|
coeff[(COLEV >> 8) & 0x1F]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
/*
|
|
||||||
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 "GBA.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GBAGfx.h"
|
#include "GBAGfx.h"
|
||||||
@ -13,20 +5,9 @@ These routines only render a single line at a time, because of the way the GBA d
|
|||||||
void mode5RenderLine()
|
void mode5RenderLine()
|
||||||
{
|
{
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -55,11 +36,11 @@ void mode5RenderLine()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
if(line2[x] < background) {
|
if(line2[x] < color) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -106,20 +87,9 @@ void mode5RenderLine()
|
|||||||
void mode5RenderLineNoWindow()
|
void mode5RenderLineNoWindow()
|
||||||
{
|
{
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -148,11 +118,11 @@ void mode5RenderLineNoWindow()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
|
|
||||||
if(line2[x] < background) {
|
if(line2[x] < color) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -172,15 +142,19 @@ void mode5RenderLineNoWindow()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((top != 0x04) && line2[x] < background) {
|
if(line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
@ -236,19 +210,9 @@ void mode5RenderLineNoWindow()
|
|||||||
void mode5RenderLineAll()
|
void mode5RenderLineAll()
|
||||||
{
|
{
|
||||||
if(DISPCNT & 0x0080) {
|
if(DISPCNT & 0x0080) {
|
||||||
|
for(int x = 0; x < 240; x++) {
|
||||||
int x = 232; //240 - 8
|
lineMix[x] = 0x7fff;
|
||||||
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;
|
gfxLastVCOUNT = VCOUNT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -304,7 +268,7 @@ void mode5RenderLineAll()
|
|||||||
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
background = ((customBackdropColor & 0x7FFF) | 0x30000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < 240; ++x) {
|
for(int x = 0; x < 240; x++) {
|
||||||
u32 color = background;
|
u32 color = background;
|
||||||
u8 top = 0x20;
|
u8 top = 0x20;
|
||||||
u8 mask = outMask;
|
u8 mask = outMask;
|
||||||
@ -324,7 +288,7 @@ void mode5RenderLineAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((mask & 4) && (line2[x] < background)) {
|
if((mask & 4) && (line2[x] < color)) {
|
||||||
color = line2[x];
|
color = line2[x];
|
||||||
top = 0x04;
|
top = 0x04;
|
||||||
}
|
}
|
||||||
@ -370,15 +334,19 @@ void mode5RenderLineAll()
|
|||||||
u32 back = background;
|
u32 back = background;
|
||||||
u8 top2 = 0x20;
|
u8 top2 = 0x20;
|
||||||
|
|
||||||
if((mask & 4) && (top != 0x04) && (line2[x] < background)) {
|
if((mask & 4) && line2[x] < back) {
|
||||||
|
if(top != 0x04) {
|
||||||
back = line2[x];
|
back = line2[x];
|
||||||
top2 = 0x04;
|
top2 = 0x04;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((mask & 16) && (top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
if((mask & 16) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) {
|
||||||
|
if(top != 0x10) {
|
||||||
back = lineOBJ[x];
|
back = lineOBJ[x];
|
||||||
top2 = 0x10;
|
top2 = 0x10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(top2 & (BLDMOD>>8))
|
if(top2 & (BLDMOD>>8))
|
||||||
color = gfxAlphaBlend(color, back,
|
color = gfxAlphaBlend(color, back,
|
||||||
|
@ -8,13 +8,21 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
// Defined in VGA-GX input.cpp
|
||||||
|
void systemCartridgeRumble(bool);
|
||||||
|
|
||||||
|
enum RTCSTATE
|
||||||
|
{
|
||||||
|
IDLE = 0,
|
||||||
|
COMMAND,
|
||||||
|
DATA,
|
||||||
|
READDATA
|
||||||
|
};
|
||||||
|
|
||||||
u8 systemGetSensorDarkness();
|
u8 systemGetSensorDarkness();
|
||||||
int systemGetSensorZ();
|
int systemGetSensorZ();
|
||||||
|
|
||||||
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 byte0;
|
u8 byte0;
|
||||||
u8 byte1;
|
u8 byte1;
|
||||||
@ -271,6 +279,17 @@ void rtcReset()
|
|||||||
rtcClockData.reserved[11] = 0;
|
rtcClockData.reserved[11] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void rtcSaveGame(u8 *&data)
|
||||||
|
{
|
||||||
|
utilWriteMem(data, &rtcClockData, sizeof(rtcClockData));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtcReadGame(const u8 *&data)
|
||||||
|
{
|
||||||
|
utilReadMem(&rtcClockData, data, sizeof(rtcClockData));
|
||||||
|
}
|
||||||
|
#else
|
||||||
void rtcSaveGame(gzFile gzFile)
|
void rtcSaveGame(gzFile gzFile)
|
||||||
{
|
{
|
||||||
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
|
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
|
||||||
@ -280,3 +299,4 @@ void rtcReadGame(gzFile gzFile)
|
|||||||
{
|
{
|
||||||
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
|
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -8,7 +8,12 @@ void rtcEnableWarioRumble(bool);
|
|||||||
bool rtcIsEnabled();
|
bool rtcIsEnabled();
|
||||||
void rtcReset();
|
void rtcReset();
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void rtcReadGame(const u8 *&data);
|
||||||
|
void rtcSaveGame(u8 *&data);
|
||||||
|
#else
|
||||||
void rtcReadGame(gzFile gzFile);
|
void rtcReadGame(gzFile gzFile);
|
||||||
void rtcSaveGame(gzFile gzFile);
|
void rtcSaveGame(gzFile gzFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RTC_H
|
#endif // RTC_H
|
||||||
|
@ -50,8 +50,8 @@ int soundTicks = SOUND_CLOCK_TICKS_;
|
|||||||
|
|
||||||
static float soundVolume = 1.0f;
|
static float soundVolume = 1.0f;
|
||||||
static int soundEnableFlag = 0x3ff; // emulator channels enabled
|
static int soundEnableFlag = 0x3ff; // emulator channels enabled
|
||||||
static float soundFiltering_ = -1.0f;
|
static float soundFiltering_ = -1;
|
||||||
static float soundVolume_ = -1.0f;
|
static float soundVolume_ = -1;
|
||||||
|
|
||||||
void interp_rate() { /* empty for now */ }
|
void interp_rate() { /* empty for now */ }
|
||||||
|
|
||||||
@ -82,8 +82,8 @@ public:
|
|||||||
int readIndex;
|
int readIndex;
|
||||||
int count;
|
int count;
|
||||||
int writeIndex;
|
int writeIndex;
|
||||||
int dac;
|
|
||||||
u8 fifo [32];
|
u8 fifo [32];
|
||||||
|
int dac;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int timer;
|
int timer;
|
||||||
@ -115,7 +115,7 @@ void Gba_Pcm::apply_control( int idx )
|
|||||||
|
|
||||||
int ch = 0;
|
int ch = 0;
|
||||||
if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) )
|
if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) )
|
||||||
ch = ioMem [SGCNT0_H+1] >> (idx <<2) & 3;
|
ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3;
|
||||||
|
|
||||||
Blip_Buffer* out = 0;
|
Blip_Buffer* out = 0;
|
||||||
switch ( ch )
|
switch ( ch )
|
||||||
@ -162,10 +162,11 @@ void Gba_Pcm::update( int dac )
|
|||||||
int filter = 0;
|
int filter = 0;
|
||||||
if ( soundInterpolation )
|
if ( soundInterpolation )
|
||||||
{
|
{
|
||||||
unsigned period = unsigned(time - last_time);
|
// base filtering on how long since last sample was output
|
||||||
unsigned idx = period >> 9;
|
int period = time - last_time;
|
||||||
|
|
||||||
if ( idx > 3 )
|
int idx = (unsigned) period / 512;
|
||||||
|
if ( idx >= 3 )
|
||||||
idx = 3;
|
idx = 3;
|
||||||
|
|
||||||
static int const filters [4] = { 0, 0, 1, 2 };
|
static int const filters [4] = { 0, 0, 1, 2 };
|
||||||
@ -182,32 +183,28 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
|
|||||||
{
|
{
|
||||||
if ( which_timer == timer && enabled )
|
if ( which_timer == timer && enabled )
|
||||||
{
|
{
|
||||||
if ( count <= 16 )
|
/* Mother 3 fix, refined to not break Metroid Fusion */
|
||||||
|
if ( count == 16 || count == 0 )
|
||||||
{
|
{
|
||||||
// Need to fill FIFO
|
// Need to fill FIFO
|
||||||
|
int saved_count = count;
|
||||||
CPUCheckDMA( 3, which ? 4 : 2 );
|
CPUCheckDMA( 3, which ? 4 : 2 );
|
||||||
if ( count <= 16 )
|
if ( saved_count == 0 && count == 16 )
|
||||||
|
CPUCheckDMA( 3, which ? 4 : 2 );
|
||||||
|
if ( count == 0 )
|
||||||
{
|
{
|
||||||
// Not filled by DMA, so fill with 16 bytes of silence
|
// Not filled by DMA, so fill with 16 bytes of silence
|
||||||
int reg = which ? FIFOB_L : FIFOA_L;
|
int reg = which ? FIFOB_L : FIFOA_L;
|
||||||
|
for ( int n = 8; n--; )
|
||||||
// No loops, yay!
|
{
|
||||||
soundEvent(reg , (u16)0);
|
|
||||||
soundEvent(reg+2, (u16)0);
|
|
||||||
//
|
|
||||||
soundEvent(reg , (u16)0);
|
|
||||||
soundEvent(reg+2, (u16)0);
|
|
||||||
//
|
|
||||||
soundEvent(reg , (u16)0);
|
|
||||||
soundEvent(reg+2, (u16)0);
|
|
||||||
//
|
|
||||||
soundEvent(reg , (u16)0);
|
soundEvent(reg , (u16)0);
|
||||||
soundEvent(reg+2, (u16)0);
|
soundEvent(reg+2, (u16)0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Read next sample from FIFO
|
// Read next sample from FIFO
|
||||||
--count;
|
count--;
|
||||||
dac = fifo [readIndex];
|
dac = fifo [readIndex];
|
||||||
readIndex = (readIndex + 1) & 31;
|
readIndex = (readIndex + 1) & 31;
|
||||||
pcm.update( dac );
|
pcm.update( dac );
|
||||||
@ -287,17 +284,14 @@ static void apply_volume( bool apu_only = false )
|
|||||||
|
|
||||||
if ( gb_apu )
|
if ( gb_apu )
|
||||||
{
|
{
|
||||||
static float const apu_vols [4] = { 0.25f, 0.5f, 1.0f, 0.25f };
|
static float const apu_vols [4] = { 0.25, 0.5, 1, 0.25 };
|
||||||
gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] );
|
gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !apu_only )
|
if ( !apu_only )
|
||||||
{
|
{
|
||||||
double tmpVol = 0.002578125 * soundVolume_; // 0.66 / 256 * soundVolume_
|
for ( int i = 0; i < 3; i++ )
|
||||||
|
pcm_synth [i].volume( 0.66 / 256 * soundVolume_ );
|
||||||
pcm_synth[0].volume( tmpVol );
|
|
||||||
pcm_synth[1].volume( tmpVol );
|
|
||||||
pcm_synth[2].volume( tmpVol );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,14 +352,19 @@ static void end_frame( blip_time_t time )
|
|||||||
|
|
||||||
void flush_samples(Multi_Buffer * buffer)
|
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
|
// 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.
|
// that don't use the length parameter of the write method.
|
||||||
// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
|
// 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.
|
// samples at once to help reducing the audio delay on all platforms.
|
||||||
int soundBufferLen = ( soundSampleRate / 60 ) << 2;
|
int soundBufferLen = ( soundSampleRate / 60 ) * 4;
|
||||||
|
|
||||||
// soundBufferLen should have a whole number of sample pairs
|
// soundBufferLen should have a whole number of sample pairs
|
||||||
assert( soundBufferLen % ((sizeof *soundFinalWave)<<1) == 0 );
|
assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 );
|
||||||
|
|
||||||
// number of samples in output buffer
|
// number of samples in output buffer
|
||||||
int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
|
int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
|
||||||
@ -380,16 +379,15 @@ void flush_samples(Multi_Buffer * buffer)
|
|||||||
soundDriver->write(soundFinalWave, soundBufferLen);
|
soundDriver->write(soundFinalWave, soundBufferLen);
|
||||||
systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
|
systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_filtering()
|
static void apply_filtering()
|
||||||
{
|
{
|
||||||
soundFiltering_ = soundFiltering;
|
soundFiltering_ = soundFiltering;
|
||||||
|
|
||||||
// Yes, I changed soundFiltering_ to soundFiltering, the reason is
|
int const base_freq = (int) (32768 - soundFiltering_ * 16384);
|
||||||
// to eliminate a write-read dependency
|
int const nyquist = stereo_buffer->sample_rate() / 2;
|
||||||
int const base_freq = 32768 - (int) (soundFiltering * 16384.0f);
|
|
||||||
int const nyquist = stereo_buffer->sample_rate() >> 1;
|
|
||||||
|
|
||||||
for ( int i = 0; i < 3; i++ )
|
for ( int i = 0; i < 3; i++ )
|
||||||
{
|
{
|
||||||
@ -458,6 +456,13 @@ static void remake_stereo_buffer()
|
|||||||
pcm [0].pcm.init();
|
pcm [0].pcm.init();
|
||||||
pcm [1].pcm.init();
|
pcm [1].pcm.init();
|
||||||
|
|
||||||
|
// APU
|
||||||
|
if ( !gb_apu )
|
||||||
|
{
|
||||||
|
gb_apu = new Gb_Apu; // TODO: handle out of memory
|
||||||
|
reset_apu();
|
||||||
|
}
|
||||||
|
|
||||||
// Stereo_Buffer
|
// Stereo_Buffer
|
||||||
delete stereo_buffer;
|
delete stereo_buffer;
|
||||||
stereo_buffer = 0;
|
stereo_buffer = 0;
|
||||||
@ -471,13 +476,7 @@ static void remake_stereo_buffer()
|
|||||||
pcm [1].which = 1;
|
pcm [1].which = 1;
|
||||||
apply_filtering();
|
apply_filtering();
|
||||||
|
|
||||||
// APU
|
// Volume Level
|
||||||
if ( !gb_apu )
|
|
||||||
{
|
|
||||||
gb_apu = new Gb_Apu; // TODO: handle out of memory
|
|
||||||
reset_apu();
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_muting();
|
apply_muting();
|
||||||
apply_volume();
|
apply_volume();
|
||||||
}
|
}
|
||||||
@ -596,8 +595,8 @@ static struct {
|
|||||||
gb_apu_state_t apu;
|
gb_apu_state_t apu;
|
||||||
|
|
||||||
// old state
|
// old state
|
||||||
int soundDSBValue;
|
|
||||||
u8 soundDSAValue;
|
u8 soundDSAValue;
|
||||||
|
int soundDSBValue;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
// Old GBA sound state format
|
// Old GBA sound state format
|
||||||
@ -755,16 +754,25 @@ static void skip_read( gzFile in, int count )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void soundSaveGame( u8 *&out )
|
||||||
|
#else
|
||||||
void soundSaveGame( gzFile out )
|
void soundSaveGame( gzFile out )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
gb_apu->save_state( &state.apu );
|
gb_apu->save_state( &state.apu );
|
||||||
|
|
||||||
// Be sure areas for expansion get written as zero
|
// Be sure areas for expansion get written as zero
|
||||||
memset( dummy_state, 0, sizeof dummy_state );
|
memset( dummy_state, 0, sizeof dummy_state );
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
utilWriteDataMem( out, gba_state );
|
||||||
|
#else
|
||||||
utilWriteData( out, gba_state );
|
utilWriteData( out, gba_state );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO__
|
||||||
static void soundReadGameOld( gzFile in, int version )
|
static void soundReadGameOld( gzFile in, int version )
|
||||||
{
|
{
|
||||||
// Read main data
|
// Read main data
|
||||||
@ -799,19 +807,28 @@ static void soundReadGameOld( gzFile in, int version )
|
|||||||
|
|
||||||
(void) utilReadInt( in ); // ignore quality
|
(void) utilReadInt( in ); // ignore quality
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void soundReadGame(const u8*& in, int version )
|
||||||
|
#else
|
||||||
void soundReadGame( gzFile in, int version )
|
void soundReadGame( gzFile in, int version )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Prepare APU and default state
|
// Prepare APU and default state
|
||||||
reset_apu();
|
reset_apu();
|
||||||
gb_apu->save_state( &state.apu );
|
gb_apu->save_state( &state.apu );
|
||||||
|
|
||||||
if ( version > SAVE_GAME_VERSION_9 )
|
if ( version > SAVE_GAME_VERSION_9 )
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
utilReadDataMem( in, gba_state );
|
||||||
|
#else
|
||||||
utilReadData( in, gba_state );
|
utilReadData( in, gba_state );
|
||||||
else
|
else
|
||||||
soundReadGameOld( in, version );
|
soundReadGameOld( in, version );
|
||||||
|
#endif
|
||||||
|
|
||||||
gb_apu->load_state( state.apu );
|
gb_apu->load_state( state.apu );
|
||||||
write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
|
write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
|
||||||
|
@ -74,8 +74,13 @@ extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to so
|
|||||||
extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
|
extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
|
||||||
|
|
||||||
// Saves/loads emulator state
|
// Saves/loads emulator state
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
void soundSaveGame( u8 *& );
|
||||||
|
void soundReadGame(const u8*& in, int version );
|
||||||
|
#else
|
||||||
void soundSaveGame( gzFile );
|
void soundSaveGame( gzFile );
|
||||||
void soundReadGame( gzFile, int version );
|
void soundReadGame( gzFile, int version );
|
||||||
|
#endif
|
||||||
|
|
||||||
class Multi_Buffer;
|
class Multi_Buffer;
|
||||||
|
|
||||||
|
@ -1058,7 +1058,7 @@ void elfParseCFA(u8 *top)
|
|||||||
|
|
||||||
if(id == 0xffffffff) {
|
if(id == 0xffffffff) {
|
||||||
// skip version
|
// skip version
|
||||||
*data++;
|
(*data)++;
|
||||||
|
|
||||||
ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
|
ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
|
||||||
|
|
||||||
|
227
source/vba/gba/gbafilter.cpp
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#include "gbafilter.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
5
source/vba/gba/gbafilter.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "../System.h"
|
||||||
|
|
||||||
|
void gbafilter_pal(u16 * buf, int count);
|
||||||
|
void gbafilter_pal32(u32 * buf, int count);
|
||||||
|
void gbafilter_pad(u8 * buf, int count);
|
@ -15,6 +15,7 @@
|
|||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wiiuse/wpad.h>
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <wupc/wupc.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
|
||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
@ -51,7 +52,8 @@ int ShutdownRequested = 0;
|
|||||||
int ResetRequested = 0;
|
int ResetRequested = 0;
|
||||||
int ExitRequested = 0;
|
int ExitRequested = 0;
|
||||||
char appPath[1024] = { 0 };
|
char appPath[1024] = { 0 };
|
||||||
char loadedFile[1024] = { 0 };
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Shutdown / Reboot / Exit
|
* Shutdown / Reboot / Exit
|
||||||
@ -341,6 +343,7 @@ int main(int argc, char *argv[])
|
|||||||
SYS_SetPowerCallback(ShutdownCB);
|
SYS_SetPowerCallback(ShutdownCB);
|
||||||
SYS_SetResetCallback(ResetCB);
|
SYS_SetResetCallback(ResetCB);
|
||||||
|
|
||||||
|
WUPC_Init();
|
||||||
WPAD_Init();
|
WPAD_Init();
|
||||||
WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB);
|
WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB);
|
||||||
DI_Init();
|
DI_Init();
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "utils/FreeTypeGX.h"
|
#include "utils/FreeTypeGX.h"
|
||||||
|
|
||||||
#define APPNAME "Visual Boy Advance GX"
|
#define APPNAME "Visual Boy Advance GX"
|
||||||
#define APPVERSION "2.2.8"
|
#define APPVERSION "2.3.3"
|
||||||
#define APPFOLDER "vbagx"
|
#define APPFOLDER "vbagx"
|
||||||
#define PREF_FILE_NAME "settings.xml"
|
#define PREF_FILE_NAME "settings.xml"
|
||||||
#define PAL_FILE_NAME "palettes.xml"
|
#define PAL_FILE_NAME "palettes.xml"
|
||||||
@ -40,7 +40,8 @@ enum {
|
|||||||
enum {
|
enum {
|
||||||
FILE_SRAM,
|
FILE_SRAM,
|
||||||
FILE_SNAPSHOT,
|
FILE_SNAPSHOT,
|
||||||
FILE_ROM
|
FILE_ROM,
|
||||||
|
FILE_BORDER_PNG
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -66,16 +67,20 @@ struct SGCSettings{
|
|||||||
float gbaZoomVert; // GBA vertical zoom amount
|
float gbaZoomVert; // GBA vertical zoom amount
|
||||||
float gbZoomHor; // GB horizontal zoom amount
|
float gbZoomHor; // GB horizontal zoom amount
|
||||||
float gbZoomVert; // GB vertical zoom amount
|
float gbZoomVert; // GB vertical zoom amount
|
||||||
|
int gbFixed;
|
||||||
|
int gbaFixed;
|
||||||
int AutoLoad;
|
int AutoLoad;
|
||||||
int AutoSave;
|
int AutoSave;
|
||||||
int LoadMethod; // For ROMS: Auto, SD, DVD, USB, Network (SMB)
|
int LoadMethod; // For ROMS: Auto, SD, DVD, USB, Network (SMB)
|
||||||
int SaveMethod; // For SRAM, Freeze, Prefs: Auto, SD, USB, SMB
|
int SaveMethod; // For SRAM, Freeze, Prefs: Auto, SD, USB, SMB
|
||||||
|
int AppendAuto; // 0 - no, 1 - yes
|
||||||
int videomode; // 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz)
|
int videomode; // 0 - automatic, 1 - NTSC (480i), 2 - Progressive (480p), 3 - PAL (50Hz), 4 - PAL (60Hz)
|
||||||
int scaling; // 0 - default, 1 - partial stretch, 2 - stretch to fit, 3 - widescreen correction
|
int scaling; // 0 - default, 1 - partial stretch, 2 - stretch to fit, 3 - widescreen correction
|
||||||
int render; // 0 - original, 1 - filtered, 2 - unfiltered
|
int render; // 0 - original, 1 - filtered, 2 - unfiltered
|
||||||
int xshift; // video output shift
|
int xshift; // video output shift
|
||||||
int yshift;
|
int yshift;
|
||||||
int colorize; // colorize Mono Gameboy games
|
int colorize; // colorize Mono Gameboy games
|
||||||
|
int gbaFrameskip; // turn on auto-frameskip for GBA games
|
||||||
int WiiControls; // Match Wii Game
|
int WiiControls; // Match Wii Game
|
||||||
int WiimoteOrientation;
|
int WiimoteOrientation;
|
||||||
int ExitAction;
|
int ExitAction;
|
||||||
@ -83,15 +88,20 @@ struct SGCSettings{
|
|||||||
int SFXVolume;
|
int SFXVolume;
|
||||||
int Rumble;
|
int Rumble;
|
||||||
int language;
|
int language;
|
||||||
|
int OffsetMinutesUTC; // Used for clock on MBC3 and TAMA5
|
||||||
|
int GBHardware; // Mapped to gbEmulatorType in VBA
|
||||||
|
int SGBBorder;
|
||||||
char LoadFolder[MAXPATHLEN]; // Path to game files
|
char LoadFolder[MAXPATHLEN]; // Path to game files
|
||||||
|
char LastFileLoaded[MAXPATHLEN]; //Last file loaded filename
|
||||||
char SaveFolder[MAXPATHLEN]; // Path to save files
|
char SaveFolder[MAXPATHLEN]; // Path to save files
|
||||||
char CheatFolder[MAXPATHLEN]; // Path to cheat files
|
char CheatFolder[MAXPATHLEN]; // Path to cheat files
|
||||||
|
char ScreenshotsFolder[MAXPATHLEN]; //Path to screenshots files
|
||||||
|
char BorderFolder[MAXPATHLEN]; // Path to Super Game Boy border files
|
||||||
char smbip[80];
|
char smbip[80];
|
||||||
char smbuser[20];
|
char smbuser[20];
|
||||||
char smbpwd[20];
|
char smbpwd[20];
|
||||||
char smbshare[20];
|
char smbshare[20];
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExitApp();
|
void ExitApp();
|
||||||
void ShutdownWii();
|
void ShutdownWii();
|
||||||
bool SupportedIOS(u32 ios);
|
bool SupportedIOS(u32 ios);
|
||||||
@ -102,7 +112,7 @@ extern int ConfigRequested;
|
|||||||
extern int ShutdownRequested;
|
extern int ShutdownRequested;
|
||||||
extern int ExitRequested;
|
extern int ExitRequested;
|
||||||
extern char appPath[];
|
extern char appPath[];
|
||||||
extern char loadedFile[];
|
|
||||||
extern FreeTypeGX *fontSystem[];
|
extern FreeTypeGX *fontSystem[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <ogc/lwp_watchdog.h>
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "vbagx.h"
|
#include "vbagx.h"
|
||||||
#include "fileop.h"
|
#include "fileop.h"
|
||||||
#include "filebrowser.h"
|
#include "filebrowser.h"
|
||||||
@ -46,6 +49,9 @@
|
|||||||
#include "vba/gb/gbCheats.h"
|
#include "vba/gb/gbCheats.h"
|
||||||
#include "vba/gb/gbSound.h"
|
#include "vba/gb/gbSound.h"
|
||||||
|
|
||||||
|
#include "goomba/goombarom.h"
|
||||||
|
#include "goomba/goombasav.h"
|
||||||
|
|
||||||
static u32 start;
|
static u32 start;
|
||||||
int cartridgeType = 0;
|
int cartridgeType = 0;
|
||||||
u32 RomIdCode;
|
u32 RomIdCode;
|
||||||
@ -72,7 +78,7 @@ int systemGreenShift = 0;
|
|||||||
int systemColorDepth = 0;
|
int systemColorDepth = 0;
|
||||||
u16 systemGbPalette[24];
|
u16 systemGbPalette[24];
|
||||||
u16 systemColorMap16[0x10000];
|
u16 systemColorMap16[0x10000];
|
||||||
u32 *systemColorMap32 = NULL;
|
u32 systemColorMap32[0x10000];
|
||||||
|
|
||||||
void gbSetPalette(u32 RRGGBB[]);
|
void gbSetPalette(u32 RRGGBB[]);
|
||||||
bool StartColorizing();
|
bool StartColorizing();
|
||||||
@ -140,6 +146,12 @@ void system10Frames(int rate)
|
|||||||
int speed = (RATE60HZ/diff)*100;
|
int speed = (RATE60HZ/diff)*100;
|
||||||
|
|
||||||
if (cartridgeType == 2) // GBA games require frameskipping
|
if (cartridgeType == 2) // GBA games require frameskipping
|
||||||
|
{
|
||||||
|
if (!GCSettings.gbaFrameskip)
|
||||||
|
{
|
||||||
|
systemFrameSkip = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// consider increasing skip
|
// consider increasing skip
|
||||||
if(speed < 60)
|
if(speed < 60)
|
||||||
@ -165,6 +177,7 @@ void system10Frames(int rate)
|
|||||||
else if(systemFrameSkip < 0)
|
else if(systemFrameSkip < 0)
|
||||||
systemFrameSkip = 0;
|
systemFrameSkip = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
lastTime = gettime();
|
lastTime = gettime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +281,34 @@ bool LoadBatteryOrState(char * filepath, int action, bool silent)
|
|||||||
// load the file into savebuffer
|
// load the file into savebuffer
|
||||||
offset = LoadFile(filepath, silent);
|
offset = LoadFile(filepath, silent);
|
||||||
|
|
||||||
|
if (cartridgeType == 1 && goomba_is_sram(savebuffer)) {
|
||||||
|
void* cleaned = goomba_cleanup(savebuffer);
|
||||||
|
if (savebuffer == NULL) {
|
||||||
|
ErrorPrompt(goomba_last_error());
|
||||||
|
offset = 0;
|
||||||
|
} else {
|
||||||
|
if (cleaned != savebuffer) {
|
||||||
|
memcpy(savebuffer, cleaned, GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
free(cleaned);
|
||||||
|
}
|
||||||
|
stateheader* sh = stateheader_for(savebuffer, RomTitle);
|
||||||
|
if (sh == NULL) {
|
||||||
|
ErrorPrompt(goomba_last_error());
|
||||||
|
offset = 0;
|
||||||
|
} else {
|
||||||
|
goomba_size_t outsize;
|
||||||
|
void* gbc_sram = goomba_extract(savebuffer, sh, &outsize);
|
||||||
|
if (gbc_sram == NULL) {
|
||||||
|
ErrorPrompt(goomba_last_error());
|
||||||
|
offset = 0;
|
||||||
|
} else {
|
||||||
|
memcpy(savebuffer, gbc_sram, outsize);
|
||||||
|
offset = outsize;
|
||||||
|
free(gbc_sram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// load savebuffer into VBA memory
|
// load savebuffer into VBA memory
|
||||||
if (offset > 0)
|
if (offset > 0)
|
||||||
{
|
{
|
||||||
@ -319,6 +360,9 @@ bool LoadBatteryOrStateAuto(int action, bool silent)
|
|||||||
if (LoadBatteryOrState(filepath, action, SILENT))
|
if (LoadBatteryOrState(filepath, action, SILENT))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (!GCSettings.AppendAuto)
|
||||||
|
return false;
|
||||||
|
|
||||||
// look for file with no number or Auto appended
|
// look for file with no number or Auto appended
|
||||||
if(!MakeFilePath(filepath2, action, ROMFilename, -1))
|
if(!MakeFilePath(filepath2, action, ROMFilename, -1))
|
||||||
return false;
|
return false;
|
||||||
@ -372,6 +416,41 @@ bool SaveBatteryOrState(char * filepath, int action, bool silent)
|
|||||||
datasize = MemgbWriteBatteryFile((char *)savebuffer);
|
datasize = MemgbWriteBatteryFile((char *)savebuffer);
|
||||||
else
|
else
|
||||||
datasize = MemCPUWriteBatteryFile((char *)savebuffer);
|
datasize = MemCPUWriteBatteryFile((char *)savebuffer);
|
||||||
|
|
||||||
|
if (cartridgeType == 1) {
|
||||||
|
const char* generic_goomba_error = "Cannot save SRAM in Goomba format (did not load correctly.)";
|
||||||
|
// check for goomba sram format
|
||||||
|
char* old_sram = (char*)malloc(GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
size_t br = LoadFile(old_sram, filepath, GOOMBA_COLOR_SRAM_SIZE, true);
|
||||||
|
if (br >= GOOMBA_COLOR_SRAM_SIZE && goomba_is_sram(old_sram)) {
|
||||||
|
void* cleaned = goomba_cleanup(old_sram);
|
||||||
|
if (cleaned == NULL) {
|
||||||
|
ErrorPrompt(generic_goomba_error);
|
||||||
|
datasize = 0;
|
||||||
|
} else {
|
||||||
|
if (cleaned != old_sram) {
|
||||||
|
free(old_sram);
|
||||||
|
old_sram = (char*)cleaned;
|
||||||
|
}
|
||||||
|
stateheader* sh = stateheader_for(old_sram, RomTitle);
|
||||||
|
if (sh == NULL) {
|
||||||
|
// Game probably doesn't use SRAM
|
||||||
|
datasize = 0;
|
||||||
|
} else {
|
||||||
|
void* new_sram = goomba_new_sav(old_sram, sh, savebuffer, datasize);
|
||||||
|
if (new_sram == NULL) {
|
||||||
|
ErrorPrompt(goomba_last_error());
|
||||||
|
datasize = 0;
|
||||||
|
} else {
|
||||||
|
memcpy(savebuffer, new_sram, GOOMBA_COLOR_SRAM_SIZE);
|
||||||
|
datasize = GOOMBA_COLOR_SRAM_SIZE;
|
||||||
|
free(new_sram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(old_sram);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -411,6 +490,30 @@ bool SaveBatteryOrStateAuto(int action, bool silent)
|
|||||||
|
|
||||||
return SaveBatteryOrState(filepath, action, silent);
|
return SaveBatteryOrState(filepath, action, silent);
|
||||||
}
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* Save Screenshot / Preview image
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int SavePreviewImg(char * filepath, bool silent)
|
||||||
|
{
|
||||||
|
int device;
|
||||||
|
|
||||||
|
if(!FindDevice(filepath, &device))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(gameScreenPngSize > 0)
|
||||||
|
{
|
||||||
|
char screenpath[1024];
|
||||||
|
strcpy(screenpath, filepath);
|
||||||
|
screenpath[strlen(screenpath)] = 0;
|
||||||
|
sprintf(screenpath, "%s.png", screenpath);
|
||||||
|
SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!silent)
|
||||||
|
InfoPrompt ("Save successful");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Sound
|
* Sound
|
||||||
@ -614,11 +717,14 @@ void systemUpdateMotionSensor()
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static int srcWidth = 0;
|
static int srcWidth = 0;
|
||||||
static int srcHeight = 0;
|
static int srcHeight = 0;
|
||||||
static int srcPitch = 0;
|
|
||||||
|
|
||||||
void systemDrawScreen()
|
void systemDrawScreen()
|
||||||
{
|
{
|
||||||
GX_Render( srcWidth, srcHeight, pix, srcPitch );
|
GX_Render(
|
||||||
|
srcWidth,
|
||||||
|
srcHeight,
|
||||||
|
pix
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ValidGameId(u32 id)
|
static bool ValidGameId(u32 id)
|
||||||
@ -710,6 +816,8 @@ static void gbApplyPerImagePreferences()
|
|||||||
RomIdCode = SWEP5;
|
RomIdCode = SWEP5;
|
||||||
else if (strcmp(RomTitle, "SRJ DMG") == 0)
|
else if (strcmp(RomTitle, "SRJ DMG") == 0)
|
||||||
RomIdCode = SWEP6;
|
RomIdCode = SWEP6;
|
||||||
|
else if (strcmp(RomTitle, "KID DRACULA") == 0)
|
||||||
|
RomIdCode = KIDDRACULA;
|
||||||
}
|
}
|
||||||
// look for matching palettes if a monochrome gameboy game
|
// look for matching palettes if a monochrome gameboy game
|
||||||
// (or if a Super Gameboy game, but the palette will be ignored later in that case)
|
// (or if a Super Gameboy game, but the palette will be ignored later in that case)
|
||||||
@ -825,11 +933,143 @@ void LoadPatch()
|
|||||||
FreeSaveBuffer ();
|
FreeSaveBuffer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SaveSGBBorderIfNoneExists(const void* buffer) {
|
||||||
|
char* borderPath = NULL;
|
||||||
|
FILE* f = NULL;
|
||||||
|
void* rgba8 = NULL;
|
||||||
|
IMGCTX pngContext = NULL;
|
||||||
|
|
||||||
|
int err;
|
||||||
|
|
||||||
|
struct stat s;
|
||||||
|
borderPath = AllocAndGetPNGBorderPath(NULL);
|
||||||
|
|
||||||
|
char* slash = strrchr(borderPath, '/');
|
||||||
|
*slash = '\0'; // cut string off at directory name
|
||||||
|
|
||||||
|
err = stat(borderPath, &s);
|
||||||
|
if (err == -1) goto cleanup;
|
||||||
|
if (!S_ISDIR(s.st_mode)) goto cleanup;
|
||||||
|
|
||||||
|
*slash = '/'; // restore slash, bring filename back
|
||||||
|
|
||||||
|
err = stat(borderPath, &s);
|
||||||
|
if (err != -1 || errno != ENOENT) goto cleanup;
|
||||||
|
|
||||||
|
f = fopen(borderPath, "wb");
|
||||||
|
if (!f) goto cleanup;
|
||||||
|
|
||||||
|
rgba8 = malloc(256*224*3);
|
||||||
|
if (!rgba8) goto cleanup;
|
||||||
|
pngContext = PNGU_SelectImageFromBuffer(rgba8);
|
||||||
|
if (pngContext == NULL) goto cleanup;
|
||||||
|
|
||||||
|
PNGU_EncodeFromLinearRGB565(pngContext, 256, 224, buffer, 258);
|
||||||
|
fwrite(rgba8, 1, 256*224*3, f);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (borderPath) free(borderPath);
|
||||||
|
if (f) fclose(f);
|
||||||
|
if (rgba8) free(rgba8);
|
||||||
|
if (pngContext) PNGU_ReleaseImageContext(pngContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* AllocAndGetPNGBorderPath(const char* title) {
|
||||||
|
const char* method = pathPrefix[GCSettings.LoadMethod];
|
||||||
|
const char* folder = GCSettings.BorderFolder;
|
||||||
|
|
||||||
|
char tmp[13];
|
||||||
|
|
||||||
|
// If no title was passed in, get the rom title
|
||||||
|
if (title == NULL) {
|
||||||
|
if (cartridgeType == 1) {
|
||||||
|
title = gb_get_title(gbRom, NULL);
|
||||||
|
} else if (cartridgeType == 2) {
|
||||||
|
memcpy(tmp, rom + 0xA0, 12);
|
||||||
|
tmp[12] = '\0';
|
||||||
|
title = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length = strlen(method) + strlen(folder) + strlen(title) + 6;
|
||||||
|
char* path = (char*)malloc(length);
|
||||||
|
if (path) sprintf(path, "%s%s/%s.png", method, folder, title);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadPNGBorder(const char* fallback)
|
||||||
|
{
|
||||||
|
void* png_tmp_buf = malloc(1024*1024);
|
||||||
|
char* borderPath = AllocAndGetPNGBorderPath(NULL);
|
||||||
|
PNGUPROP imgProp;
|
||||||
|
IMGCTX ctx = NULL;
|
||||||
|
char error[1024]; error[1023] = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
bool borderLoaded = LoadFile((char*)png_tmp_buf, borderPath, 1024*1024, SILENT);
|
||||||
|
if (!borderLoaded) {
|
||||||
|
// Try default border.png
|
||||||
|
free(borderPath);
|
||||||
|
borderPath = AllocAndGetPNGBorderPath(fallback);
|
||||||
|
borderLoaded = LoadFile((char*)png_tmp_buf, borderPath, 1024*1024, SILENT);
|
||||||
|
}
|
||||||
|
if (!borderLoaded) goto cleanup;
|
||||||
|
|
||||||
|
ctx = PNGU_SelectImageFromBuffer(png_tmp_buf);
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
snprintf(error, 1023, "Error reading %s", borderPath);
|
||||||
|
ErrorPrompt(error);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = PNGU_GetImageProperties(ctx, &imgProp);
|
||||||
|
if (r != PNGU_OK) {
|
||||||
|
snprintf(error, 1023, "PNGU properties error (%d): %s", r, borderPath);
|
||||||
|
ErrorPrompt(error);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imgProp.imgWidth > 640 || imgProp.imgHeight > 480) {
|
||||||
|
snprintf(error, 1023, "Wrong size (should be 640x480 or smaller): %s", borderPath);
|
||||||
|
ErrorPrompt(error);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitialBorder = (u16*)malloc(640*480*2);
|
||||||
|
r = PNGU_DecodeTo4x4RGB565 (ctx, imgProp.imgWidth, imgProp.imgHeight, InitialBorder);
|
||||||
|
if (r != PNGU_OK) {
|
||||||
|
snprintf(error, 1023, "PNGU decoding error (%d): %s", r, borderPath);
|
||||||
|
ErrorPrompt(error);
|
||||||
|
free(InitialBorder);
|
||||||
|
InitialBorder = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitialBorderWidth = imgProp.imgWidth;
|
||||||
|
InitialBorderHeight = imgProp.imgHeight;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (png_tmp_buf) free(png_tmp_buf);
|
||||||
|
if (borderPath) free(borderPath);
|
||||||
|
if (ctx) PNGU_ReleaseImageContext(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
extern bool gbUpdateSizes();
|
extern bool gbUpdateSizes();
|
||||||
|
|
||||||
bool LoadGBROM()
|
bool LoadGBROM()
|
||||||
{
|
{
|
||||||
gbRom = (u8 *)malloc(1024*1024*4); // allocate 4 MB to GB ROM
|
gbEmulatorType = GCSettings.GBHardware;
|
||||||
|
|
||||||
|
if (browserList[browser.selIndex].length > 1024*1024*8) {
|
||||||
|
InfoPrompt("ROM size is too large (> 8 MB)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gbRom = (u8 *)malloc(1024*1024*8); // 32 MB is too much for sure
|
||||||
|
if (!gbRom) {
|
||||||
|
InfoPrompt("Unable to allocate 8 MB of memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bios = (u8 *)calloc(1,0x100);
|
bios = (u8 *)calloc(1,0x100);
|
||||||
|
|
||||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||||
@ -848,16 +1088,51 @@ bool LoadGBROM()
|
|||||||
gbRomSize = LoadSzFile(szpath, (unsigned char *)gbRom);
|
gbRomSize = LoadSzFile(szpath, (unsigned char *)gbRom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* firstRom = gb_first_rom(gbRom, gbRomSize);
|
||||||
|
const void* secondRom = gb_next_rom(gbRom, gbRomSize, firstRom);
|
||||||
|
if (firstRom != NULL && firstRom != gbRom) {
|
||||||
|
char msgbuf[32];
|
||||||
|
const void* rom;
|
||||||
|
for (rom = firstRom; rom != NULL; rom = gb_next_rom(gbRom, gbRomSize, rom)) {
|
||||||
|
sprintf(msgbuf, "Load %s?", gb_get_title(rom, NULL));
|
||||||
|
if (secondRom == NULL || YesNoPrompt(msgbuf, true)) {
|
||||||
|
gbRomSize = gb_rom_size(rom);
|
||||||
|
memmove(gbRom, rom, gbRomSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rom == NULL) {
|
||||||
|
InfoPrompt("No more ROMs found in the file.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GCSettings.SGBBorder == 2) LoadPNGBorder("default");
|
||||||
|
|
||||||
if(gbRomSize <= 0)
|
if(gbRomSize <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return gbUpdateSizes();
|
return gbUpdateSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool utilIsZipFile(const char* file)
|
||||||
|
{
|
||||||
|
if(strlen(file) > 4)
|
||||||
|
{
|
||||||
|
char * p = strrchr(file,'.');
|
||||||
|
if(p != NULL)
|
||||||
|
{
|
||||||
|
if(strcasecmp(p, ".zip") == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool LoadVBAROM()
|
bool LoadVBAROM()
|
||||||
{
|
{
|
||||||
cartridgeType = 0;
|
cartridgeType = 0;
|
||||||
bool loaded = false;
|
int loaded = 0;
|
||||||
|
|
||||||
// image type (checks file extension)
|
// image type (checks file extension)
|
||||||
if(utilIsGBAImage(browserList[browser.selIndex].filename))
|
if(utilIsGBAImage(browserList[browser.selIndex].filename))
|
||||||
@ -907,27 +1182,36 @@ bool LoadVBAROM()
|
|||||||
|
|
||||||
srcWidth = 0;
|
srcWidth = 0;
|
||||||
srcHeight = 0;
|
srcHeight = 0;
|
||||||
srcPitch = 0;
|
|
||||||
|
|
||||||
VMClose(); // cleanup GBA memory
|
VMClose(); // cleanup GBA memory
|
||||||
gbCleanUp(); // cleanup GB memory
|
gbCleanUp(); // cleanup GB memory
|
||||||
|
|
||||||
switch(cartridgeType)
|
if (InitialBorder != NULL) {
|
||||||
|
free(InitialBorder);
|
||||||
|
InitialBorder = NULL;
|
||||||
|
}
|
||||||
|
SGBBorderLoadedFromGame = false; // don't try to copy sgb border from game to png unless we're in sgb mode
|
||||||
|
|
||||||
|
if(cartridgeType == 2)
|
||||||
{
|
{
|
||||||
case 2:
|
|
||||||
emulator = GBASystem;
|
emulator = GBASystem;
|
||||||
srcWidth = 240;
|
srcWidth = 240;
|
||||||
srcHeight = 160;
|
srcHeight = 160;
|
||||||
loaded = VMCPULoadROM();
|
loaded = VMCPULoadROM();
|
||||||
srcPitch = 484;
|
|
||||||
soundSetSampleRate(22050); //44100 / 2
|
soundSetSampleRate(22050); //44100 / 2
|
||||||
cpuSaveType = 0;
|
cpuSaveType = 0;
|
||||||
break;
|
if (loaded == 2) {
|
||||||
|
loaded = 0;
|
||||||
|
cartridgeType = 1;
|
||||||
|
} else if (loaded == 1 && GCSettings.SGBBorder == 2) {
|
||||||
|
LoadPNGBorder("defaultgba");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
if (cartridgeType == 1)
|
||||||
|
{
|
||||||
emulator = GBSystem;
|
emulator = GBSystem;
|
||||||
|
gbBorderOn = (GCSettings.SGBBorder == 1);
|
||||||
gbBorderOn = 0; // GB borders always off
|
|
||||||
|
|
||||||
if(gbBorderOn)
|
if(gbBorderOn)
|
||||||
{
|
{
|
||||||
@ -936,6 +1220,7 @@ bool LoadVBAROM()
|
|||||||
gbBorderLineSkip = 256;
|
gbBorderLineSkip = 256;
|
||||||
gbBorderColumnSkip = 48;
|
gbBorderColumnSkip = 48;
|
||||||
gbBorderRowSkip = 40;
|
gbBorderRowSkip = 40;
|
||||||
|
SGBBorderLoadedFromGame = false; // try to load the border during rendering
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -947,9 +1232,7 @@ bool LoadVBAROM()
|
|||||||
}
|
}
|
||||||
|
|
||||||
loaded = LoadGBROM();
|
loaded = LoadGBROM();
|
||||||
srcPitch = 324;
|
|
||||||
soundSetSampleRate(44100);
|
soundSetSampleRate(44100);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!loaded)
|
if(!loaded)
|
||||||
@ -960,7 +1243,11 @@ bool LoadVBAROM()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Setup GX
|
// Setup GX
|
||||||
|
if (InitialBorder) {
|
||||||
|
GX_Render_Init(InitialBorderWidth, InitialBorderHeight);
|
||||||
|
} else {
|
||||||
GX_Render_Init(srcWidth, srcHeight);
|
GX_Render_Init(srcWidth, srcHeight);
|
||||||
|
}
|
||||||
|
|
||||||
if (cartridgeType == 1)
|
if (cartridgeType == 1)
|
||||||
{
|
{
|
||||||
@ -1023,9 +1310,9 @@ void InitialisePalette()
|
|||||||
// Build GBPalette
|
// Build GBPalette
|
||||||
for( i = 0; i < 24; )
|
for( i = 0; i < 24; )
|
||||||
{
|
{
|
||||||
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
|
systemGbPalette[i++] = (0x1c) | (0x1e << 5) | (0x1c << 10);
|
||||||
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
|
systemGbPalette[i++] = (0x10) | (0x17 << 5) | (0x0b << 10);
|
||||||
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
|
systemGbPalette[i++] = (0x27) | (0x0c << 5) | (0x0a << 10);
|
||||||
systemGbPalette[i++] = 0;
|
systemGbPalette[i++] = 0;
|
||||||
}
|
}
|
||||||
// Set palette etc - Fixed to RGB565
|
// Set palette etc - Fixed to RGB565
|
||||||
|
@ -28,5 +28,6 @@ bool LoadBatteryOrState(char * filepath, int action, bool silent);
|
|||||||
bool LoadBatteryOrStateAuto(int action, bool silent);
|
bool LoadBatteryOrStateAuto(int action, bool silent);
|
||||||
bool SaveBatteryOrState(char * filepath, int action, bool silent);
|
bool SaveBatteryOrState(char * filepath, int action, bool silent);
|
||||||
bool SaveBatteryOrStateAuto(int action, bool silent);
|
bool SaveBatteryOrStateAuto(int action, bool silent);
|
||||||
|
bool SavePreviewImg (char * filepath, bool silent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
181
source/video.cpp
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
|
#include <ogc/machine/processor.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#include "vbagx.h"
|
#include "vbagx.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "vbasupport.h"
|
||||||
|
|
||||||
s32 CursorX, CursorY;
|
s32 CursorX, CursorY;
|
||||||
bool CursorVisible;
|
bool CursorVisible;
|
||||||
@ -41,6 +43,11 @@ int gameScreenPngSize = 0;
|
|||||||
int screenheight = 480;
|
int screenheight = 480;
|
||||||
int screenwidth = 640;
|
int screenwidth = 640;
|
||||||
|
|
||||||
|
u16 *InitialBorder = NULL;
|
||||||
|
int InitialBorderWidth = 0;
|
||||||
|
int InitialBorderHeight = 0;
|
||||||
|
bool SGBBorderLoadedFromGame = false;
|
||||||
|
|
||||||
/*** 3D GX ***/
|
/*** 3D GX ***/
|
||||||
#define DEFAULT_FIFO_SIZE ( 256 * 1024 )
|
#define DEFAULT_FIFO_SIZE ( 256 * 1024 )
|
||||||
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
|
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
@ -160,7 +167,7 @@ static inline void draw_init(void)
|
|||||||
|
|
||||||
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
||||||
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||||
if (!(GCSettings.render&1))
|
if (GCSettings.render == 2)
|
||||||
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +253,7 @@ static inline void draw_cursor(Mtx v)
|
|||||||
|
|
||||||
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
||||||
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||||
if (!(GCSettings.render&1))
|
if (GCSettings.render == 2)
|
||||||
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -290,6 +297,12 @@ static GXRModeObj * FindVideoMode()
|
|||||||
case 4: // PAL (60Hz)
|
case 4: // PAL (60Hz)
|
||||||
mode = &TVEurgb60Hz480IntDf;
|
mode = &TVEurgb60Hz480IntDf;
|
||||||
break;
|
break;
|
||||||
|
case 5: // NTSC (240p)
|
||||||
|
mode = &TVNtsc240Ds;
|
||||||
|
break;
|
||||||
|
case 6: // PAL (60Hz 240p)
|
||||||
|
mode = &TVEurgb60Hz240Ds;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
mode = VIDEO_GetPreferredMode(NULL);
|
mode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
@ -316,7 +329,7 @@ static GXRModeObj * FindVideoMode()
|
|||||||
if (mode == &TVPal576IntDfScale)
|
if (mode == &TVPal576IntDfScale)
|
||||||
pal = true;
|
pal = true;
|
||||||
|
|
||||||
if (CONF_GetAspectRatio() == CONF_ASPECT_16_9)
|
/*if (CONF_GetAspectRatio() == CONF_ASPECT_16_9 && mode->xfbHeight != 240)
|
||||||
{
|
{
|
||||||
if (pal)
|
if (pal)
|
||||||
{
|
{
|
||||||
@ -334,9 +347,9 @@ static GXRModeObj * FindVideoMode()
|
|||||||
mode->efbHeight = 456;
|
mode->efbHeight = 456;
|
||||||
mode->viWidth = 686;
|
mode->viWidth = 686;
|
||||||
}
|
}
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
mode->viWidth = 672;
|
mode->viWidth = 704;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pal)
|
if (pal)
|
||||||
@ -453,10 +466,7 @@ static inline void UpdateScaling()
|
|||||||
TvAspectRatio = 4.0f/3.0f;
|
TvAspectRatio = 4.0f/3.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (vwidth == 240) // GBA
|
GameboyAspectRatio = ((vwidth * 1.0) / vheight);
|
||||||
GameboyAspectRatio = 240.0f/160.0f; // assumes square pixels on GB Advance
|
|
||||||
else // GB or GBC
|
|
||||||
GameboyAspectRatio = 160.0f/144.0f; // assumes square pixels on GB Colour
|
|
||||||
|
|
||||||
if (TvAspectRatio>GameboyAspectRatio)
|
if (TvAspectRatio>GameboyAspectRatio)
|
||||||
{
|
{
|
||||||
@ -476,17 +486,37 @@ static inline void UpdateScaling()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// change zoom
|
// change zoom
|
||||||
if (vwidth == 240) // GBA
|
float zoomHor, zoomVert;
|
||||||
|
int fixed;
|
||||||
|
if (cartridgeType == 2) // GBA
|
||||||
{
|
{
|
||||||
xscale *= GCSettings.gbaZoomHor;
|
zoomHor = GCSettings.gbaZoomHor;
|
||||||
yscale *= GCSettings.gbaZoomVert;
|
zoomVert = GCSettings.gbaZoomVert;
|
||||||
|
fixed = GCSettings.gbaFixed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xscale *= GCSettings.gbZoomHor;
|
zoomHor = GCSettings.gbZoomHor;
|
||||||
yscale *= GCSettings.gbZoomVert;
|
zoomVert = GCSettings.gbZoomVert;
|
||||||
|
fixed = GCSettings.gbFixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fixed) {
|
||||||
|
xscale = 320;
|
||||||
|
yscale = 240;
|
||||||
|
} else {
|
||||||
|
xscale *= zoomHor;
|
||||||
|
yscale *= zoomVert;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if (fixed && CONF_GetAspectRatio() == CONF_ASPECT_16_9 && (*(u32*)(0xCD8005A0) >> 16) == 0xCAFE) // Wii U
|
||||||
|
{
|
||||||
|
/* vWii widescreen patch by tueidj */
|
||||||
|
write32(0xd8006a0, fixed ? 0x30000002 : 0x30000004), mask32(0xd8006a8, 0, 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set new aspect
|
// Set new aspect
|
||||||
square[0] = square[9] = -xscale + GCSettings.xshift;
|
square[0] = square[9] = -xscale + GCSettings.xshift;
|
||||||
square[3] = square[6] = xscale + GCSettings.xshift;
|
square[3] = square[6] = xscale + GCSettings.xshift;
|
||||||
@ -498,7 +528,23 @@ static inline void UpdateScaling()
|
|||||||
|
|
||||||
memset(&view, 0, sizeof(Mtx));
|
memset(&view, 0, sizeof(Mtx));
|
||||||
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
||||||
|
if (fixed) {
|
||||||
|
int ratio = fixed % 10;
|
||||||
|
bool widescreen = fixed / 10;
|
||||||
|
|
||||||
|
float vw = vwidth * ratio;
|
||||||
|
if (widescreen) vw /= 4.0 / 3.0;
|
||||||
|
float vh = vheight * ratio;
|
||||||
|
|
||||||
|
// 240p adjustment
|
||||||
|
if (GCSettings.videomode == 5 || GCSettings.videomode == 6) vw *= 2;
|
||||||
|
|
||||||
|
float vx = (vmode->fbWidth - vw) / 2;
|
||||||
|
float vy = (vmode->efbHeight - vh) / 2;
|
||||||
|
GX_SetViewport(vx, vy, vw, vh, 0, 1);
|
||||||
|
} else {
|
||||||
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
updateScaling = 0;
|
updateScaling = 0;
|
||||||
}
|
}
|
||||||
@ -523,7 +569,13 @@ ResetVideo_Emu ()
|
|||||||
|
|
||||||
GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight);
|
GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||||
GX_SetDispCopyDst (rmode->fbWidth, rmode->xfbHeight);
|
GX_SetDispCopyDst (rmode->fbWidth, rmode->xfbHeight);
|
||||||
GX_SetCopyFilter (rmode->aa, rmode->sample_pattern, (GCSettings.render == 1) ? GX_TRUE : GX_FALSE, rmode->vfilter); // deflickering filter only for filtered mode
|
u8 sharp[7] = {0,0,21,22,21,0,0};
|
||||||
|
u8 soft[7] = {8,8,10,12,10,8,8};
|
||||||
|
u8* vfilter =
|
||||||
|
GCSettings.render == 3 ? sharp
|
||||||
|
: GCSettings.render == 4 ? soft
|
||||||
|
: rmode->vfilter;
|
||||||
|
GX_SetCopyFilter (rmode->aa, rmode->sample_pattern, (GCSettings.render != 2) ? GX_TRUE : GX_FALSE, vfilter); // deflickering filter only for filtered mode
|
||||||
|
|
||||||
GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||||
|
|
||||||
@ -542,7 +594,7 @@ ResetVideo_Emu ()
|
|||||||
// reinitialize texture
|
// reinitialize texture
|
||||||
GX_InvalidateTexAll ();
|
GX_InvalidateTexAll ();
|
||||||
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); // initialize the texture obj we are going to use
|
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); // initialize the texture obj we are going to use
|
||||||
if (!(GCSettings.render&1))
|
if (GCSettings.render == 2)
|
||||||
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
|
||||||
|
|
||||||
GX_Flush();
|
GX_Flush();
|
||||||
@ -569,26 +621,55 @@ void GX_Render_Init(int width, int height)
|
|||||||
vheight = height;
|
vheight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool borderAreaEmpty(const u16* buffer) {
|
||||||
|
u16 reference = buffer[0];
|
||||||
|
for (int y=0; y<40; y++) {
|
||||||
|
for (int x=0; x<256; x++) {
|
||||||
|
if (buffer[258*y + x] != reference) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int y=40; y<184; y++) {
|
||||||
|
for (int x=0; x<48; x++) {
|
||||||
|
if (buffer[258*y + x] != reference) return false;
|
||||||
|
}
|
||||||
|
for (int x=208; x<224; x++) {
|
||||||
|
if (buffer[258*y + x] != reference) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int y=184; y<224; y++) {
|
||||||
|
for (int x=0; x<256; x++) {
|
||||||
|
if (buffer[258*y + x] != reference) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* GX_Render
|
* GX_Render
|
||||||
*
|
*
|
||||||
* Pass in a buffer, width and height to update as a tiled RGB565 texture
|
* Pass in a buffer, width and height to update as a tiled RGB565 texture
|
||||||
|
* (2 bytes per pixel)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void GX_Render(int width, int height, u8 * buffer, int pitch)
|
void GX_Render(int gbWidth, int gbHeight, u8 * buffer)
|
||||||
{
|
{
|
||||||
|
int borderWidth = InitialBorder ? InitialBorderWidth : gbWidth;
|
||||||
|
int borderHeight = InitialBorder ? InitialBorderHeight : gbHeight;
|
||||||
|
|
||||||
int h, w;
|
int h, w;
|
||||||
long long int *dst = (long long int *) texturemem;
|
int gbPitch = gbWidth * 2 + 4;
|
||||||
|
long long int *dst = (long long int *) texturemem; // Pointer in 8-byte units / 4-pixel units
|
||||||
long long int *src1 = (long long int *) buffer;
|
long long int *src1 = (long long int *) buffer;
|
||||||
long long int *src2 = (long long int *) (buffer + pitch);
|
long long int *src2 = (long long int *) (buffer + gbPitch);
|
||||||
long long int *src3 = (long long int *) (buffer + (pitch << 1));
|
long long int *src3 = (long long int *) (buffer + (gbPitch << 1));
|
||||||
long long int *src4 = (long long int *) (buffer + (pitch * 3));
|
long long int *src4 = (long long int *) (buffer + (gbPitch * 3));
|
||||||
int rowpitch = (pitch >> 3) * 3;
|
int srcrowpitch = (gbPitch >> 3) * 3;
|
||||||
int rowadjust = ( pitch % 8 ) << 2;
|
int srcrowadjust = ( gbPitch % 8 ) << 2;
|
||||||
|
int dstrowpitch = borderWidth - gbWidth;
|
||||||
|
|
||||||
vwidth = width;
|
vwidth = borderWidth;
|
||||||
vheight = height;
|
vheight = borderHeight;
|
||||||
|
|
||||||
int vwid2 = (vwidth >> 2);
|
int vwid2 = (gbWidth >> 2);
|
||||||
char *ra = NULL;
|
char *ra = NULL;
|
||||||
|
|
||||||
// Ensure previous vb has complete
|
// Ensure previous vb has complete
|
||||||
@ -606,7 +687,26 @@ void GX_Render(int width, int height, u8 * buffer, int pitch)
|
|||||||
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
|
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
|
||||||
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||||
|
|
||||||
for (h = 0; h < vheight; h += 4)
|
if (gbWidth == 256 && gbHeight == 224 && !SGBBorderLoadedFromGame) {
|
||||||
|
if (borderAreaEmpty((u16*)buffer)) {
|
||||||
|
// TODO: don't paint empty SGB border
|
||||||
|
} else {
|
||||||
|
// don't try to load the default border anymore
|
||||||
|
SGBBorderLoadedFromGame = true;
|
||||||
|
SaveSGBBorderIfNoneExists(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The InitialBorder, if any, should already be properly tiled
|
||||||
|
if (InitialBorder) {
|
||||||
|
memcpy(dst, InitialBorder, borderWidth * borderHeight * 2);
|
||||||
|
|
||||||
|
int rows_to_skip = (borderHeight - gbHeight) / 2;
|
||||||
|
if (rows_to_skip > 0) dst += rows_to_skip * borderWidth / 4;
|
||||||
|
dst += (borderWidth - gbWidth) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (h = 0; h < gbHeight; h += 4)
|
||||||
{
|
{
|
||||||
for (w = 0; w < vwid2; ++w)
|
for (w = 0; w < vwid2; ++w)
|
||||||
{
|
{
|
||||||
@ -616,21 +716,22 @@ void GX_Render(int width, int height, u8 * buffer, int pitch)
|
|||||||
*dst++ = *src4++;
|
*dst++ = *src4++;
|
||||||
}
|
}
|
||||||
|
|
||||||
src1 += rowpitch;
|
src1 += srcrowpitch;
|
||||||
src2 += rowpitch;
|
src2 += srcrowpitch;
|
||||||
src3 += rowpitch;
|
src3 += srcrowpitch;
|
||||||
src4 += rowpitch;
|
src4 += srcrowpitch;
|
||||||
|
dst += dstrowpitch;
|
||||||
|
|
||||||
if ( rowadjust )
|
if ( srcrowadjust )
|
||||||
{
|
{
|
||||||
ra = (char *)src1;
|
ra = (char *)src1;
|
||||||
src1 = (long long int *)(ra + rowadjust);
|
src1 = (long long int *)(ra + srcrowadjust);
|
||||||
ra = (char *)src2;
|
ra = (char *)src2;
|
||||||
src2 = (long long int *)(ra + rowadjust);
|
src2 = (long long int *)(ra + srcrowadjust);
|
||||||
ra = (char *)src3;
|
ra = (char *)src3;
|
||||||
src3 = (long long int *)(ra + rowadjust);
|
src3 = (long long int *)(ra + srcrowadjust);
|
||||||
ra = (char *)src4;
|
ra = (char *)src4;
|
||||||
src4 = (long long int *)(ra + rowadjust);
|
src4 = (long long int *)(ra + srcrowadjust);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,6 +791,14 @@ void TakeScreenshot()
|
|||||||
void
|
void
|
||||||
ResetVideo_Menu ()
|
ResetVideo_Menu ()
|
||||||
{
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if (CONF_GetAspectRatio() == CONF_ASPECT_16_9 && (*(u32*)(0xCD8005A0) >> 16) == 0xCAFE) // Wii U
|
||||||
|
{
|
||||||
|
/* vWii widescreen patch by tueidj */
|
||||||
|
write32(0xd8006a0, 0x30000004), mask32(0xd8006a8, 0, 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Mtx44 p;
|
Mtx44 p;
|
||||||
f32 yscale;
|
f32 yscale;
|
||||||
u32 xfbHeight;
|
u32 xfbHeight;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
void InitializeVideo ();
|
void InitializeVideo ();
|
||||||
void GX_Render_Init(int width, int height);
|
void GX_Render_Init(int width, int height);
|
||||||
void GX_Render(int width, int height, u8 * buffer, int pitch);
|
void GX_Render(int gbWidth, int gbHeight, u8 * buffer);
|
||||||
void StopGX();
|
void StopGX();
|
||||||
void ResetVideo_Emu();
|
void ResetVideo_Emu();
|
||||||
void ResetVideo_Menu();
|
void ResetVideo_Menu();
|
||||||
@ -38,4 +38,11 @@ extern u8 * gameScreenPng;
|
|||||||
extern int gameScreenPngSize;
|
extern int gameScreenPngSize;
|
||||||
extern u32 FrameTimer;
|
extern u32 FrameTimer;
|
||||||
|
|
||||||
|
char *AllocAndGetPNGBorderPath(const char* title);
|
||||||
|
void SaveSGBBorderIfNoneExists(const void* buffer);
|
||||||
|
extern u16 *InitialBorder;
|
||||||
|
extern int InitialBorderWidth;
|
||||||
|
extern int InitialBorderHeight;
|
||||||
|
extern bool SGBBorderLoadedFromGame;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "vba/gba/Globals.h"
|
#include "vba/gba/Globals.h"
|
||||||
#include "vba/Util.h"
|
#include "vba/Util.h"
|
||||||
#include "vba/common/Port.h"
|
#include "vba/common/Port.h"
|
||||||
|
#include "goomba/goombarom.h"
|
||||||
|
|
||||||
#define MEM_BAD 0xff
|
#define MEM_BAD 0xff
|
||||||
#define MEM_VM 0x01
|
#define MEM_VM 0x01
|
||||||
@ -152,10 +153,9 @@ static void VMAllocGBA( void )
|
|||||||
* MEM2 version of GBA CPULoadROM
|
* MEM2 version of GBA CPULoadROM
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool VMCPULoadROM()
|
int VMCPULoadROM()
|
||||||
{
|
{
|
||||||
VMClose();
|
VMClose();
|
||||||
VMAllocGBA();
|
|
||||||
GBAROMSize = 0;
|
GBAROMSize = 0;
|
||||||
|
|
||||||
if(!inSz)
|
if(!inSz)
|
||||||
@ -163,7 +163,7 @@ bool VMCPULoadROM()
|
|||||||
char filepath[1024];
|
char filepath[1024];
|
||||||
|
|
||||||
if(!MakeFilePath(filepath, FILE_ROM))
|
if(!MakeFilePath(filepath, FILE_ROM))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
GBAROMSize = LoadFile ((char *)rom, filepath, browserList[browser.selIndex].length, NOTSILENT);
|
GBAROMSize = LoadFile ((char *)rom, filepath, browserList[browser.selIndex].length, NOTSILENT);
|
||||||
}
|
}
|
||||||
@ -172,17 +172,26 @@ bool VMCPULoadROM()
|
|||||||
GBAROMSize = LoadSzFile(szpath, (unsigned char *)rom);
|
GBAROMSize = LoadSzFile(szpath, (unsigned char *)rom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(gb_first_rom(rom, GBAROMSize)) {
|
||||||
|
int r = YesNoPrompt("This file contains uncompressed Game Boy (Color) ROMs. Do you want to run these?", true);
|
||||||
|
if (r) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VMAllocGBA();
|
||||||
|
|
||||||
if(GBAROMSize)
|
if(GBAROMSize)
|
||||||
{
|
{
|
||||||
flashInit();
|
flashInit();
|
||||||
eepromInit();
|
eepromInit();
|
||||||
CPUUpdateRenderBuffers( true );
|
CPUUpdateRenderBuffers( true );
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VMClose();
|
VMClose();
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#ifndef __VBAVMHDR__
|
#ifndef __VBAVMHDR__
|
||||||
#define __VBAVMHDR__
|
#define __VBAVMHDR__
|
||||||
|
|
||||||
bool VMCPULoadROM();
|
int VMCPULoadROM();
|
||||||
void VMClose();
|
void VMClose();
|
||||||
|
|
||||||
#ifdef USE_VM
|
#ifdef USE_VM
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<app version="2.2.8">
|
<app version="2.2.8">
|
||||||
<file url="http://vba-wii.googlecode.com/files/Visual%20Boy%20Advance%20GX%202.2.8.zip"></file>
|
<file url="http://github.com/dborth/vba-wii/releases/download/2.2.8/Visual.Boy.Advance.GX.2.2.8.zip"></file>
|
||||||
</app>
|
</app>
|
||||||
|